Phase 7: cockpit overlay generator, region extraction, and profile editor

Overlay generator (pure, tested) — RioJoy.Core/Overlay:
- FontFitter ports the legacy calc-fontsize auto-fit search (validated against a
  brute-force oracle); OverlayLayoutEngine ports create-data-layer's fit + h/v
  justification and adds per-region 90 deg CCW rotation; OverlayTemplate/Region +
  OverlayTemplateStore hold cell geometry/colour/rotation (regions.json).
- GoobieDataImporter parses the legacy .data label sheet into label rows.
- src/RioJoy.Overlay: SkiaSharp rasterizer (SkiaTextMeasurer shared with the engine
  so measured layout == drawn output; SkiaOverlayRenderer -> PNG;
  ProfileWallpaperGenerator). Verified end-to-end on the real cockpit art
  (regions.json + riojoy.png + TEST.data) by OverlayRenderIntegrationTests.
- RioJoy.Tray/WallpaperApplier applies via SystemParametersInfo; RioCoordinator
  generates+applies on profile activation (opt-in via AppConfig.OverlayTemplatePath).

Region geometry — tools/XcfRegionExtract parses riojoy.xcf (a GIMP-format binary
reader, no GIMP needed) into the 119-cell regions.json: per-layer offsets/size/
font/colour, with 90 deg CCW rotation on a-00 + b-10..b-1F. Base image riojoy.png.
NOTE: the wallpaper positions are a VGA chroma-split display artifact (6 displays),
not the cockpit's logical layout.

Mapping editor (first cut) — RioJoy.Tray/Editor/ProfileEditorForm renders the
config sheet's logical grid (SheetLayout parses the sheet CSV export). The iRIO
word is edited via ButtonBinding <-> RioMapEntry.Create (no hex bit-twiddling), with
a context-sensitive picker: keyboard keys by name (KeyCatalog VK names), joystick
Button N, hat direction, mouse/RIO-command enum names; modifiers only for keyboard.
Opened from the tray ("Edit profile..."). The sheet-grid layout is a starting point
that needs rework from a better-formatted source.

~220 xUnit tests green. Docs (PLAN.md, README) updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-06-27 17:13:48 -05:00
co-authored by Claude Opus 4.8
parent 2deeb374ae
commit 8d2d0b71aa
47 changed files with 3866 additions and 21 deletions
+47 -13
View File
@@ -100,7 +100,7 @@ tray menu is always available.
## Phases
### Phase 0 — Repo & scaffold ✅ (this commit)
- `git init`, remote `https://gitea.mysticmachines.com/VWE/riovjoy2.git`.
- `git init`, remote `https://gitea.mysticmachines.com/VWE/RIOJoy.git`.
- Legacy C++ moved to `legacy/`; cockpit art to `docs/reference/`.
- Solution `RioJoy.sln` with `src/RioJoy.Core` (lib) + `src/RioJoy.Tray`
(tray app); `driver/` placeholder for the WDK project.
@@ -183,7 +183,7 @@ Implemented in `src/RioJoy.Core/Calibration` + `Plasma` (105 xUnit tests total):
### Phase 5 — Tray app + profiles — code-complete ✅
Core logic in `src/RioJoy.Core/Profiles` + `RioRuntime`; UI/OS in `src/RioJoy.Tray`
(123 xUnit tests total):
(136 xUnit tests total across the suite):
- `RioProfile` + `AppConfig` model; `ConfigStore` JSON persistence (round-trip
tested); `RioIniImporter` ports the legacy `RIO.ini` (buttons/inverts/greeting).
- `AutoSwitchResolver` + `AutoSwitchWatcher`: the three-state decision
@@ -205,20 +205,54 @@ Core logic in `src/RioJoy.Core/Profiles` + `RioRuntime`; UI/OS in `src/RioJoy.Tr
acquire/release lifecycle against real RIO hardware.
### Phase 6 — Packaging / signing / deploy
- Driver install via `pnputil`; app installer; test-signing script.
- Cabinet deployment doc. (Production option: attestation signing.)
- Driver test-signing + `pnputil` install already scripted (`driver/sign.ps1`,
`driver/install.ps1`, `driver/uninstall.ps1`, [`driver/README.md`](../driver/README.md));
proven on the cabinet. ⏳ Still to do: app installer, a single bundled deploy,
and a cabinet deployment doc. (Production option: attestation signing.)
### Phase 7 — Profile/mapping editor + cockpit overlay generator
### Phase 7 — Profile/mapping editor + cockpit overlay generator — in progress
Replaces the legacy Google-Sheet → `.data` → GIMP → Script-Fu pipeline
(see [`docs/reference/customBackground/`](reference/customBackground/)).
- **Mapping editor:** per-button UI to set action + label + lamp, no hex
bit-twiddling; clone-from-existing profile.
- **Overlay generator:** render labels into named regions over a base cockpit
image using **SkiaSharp**, porting the auto-fit/justification logic from
`sg-goobie-MFD.scm`; export the per-profile wallpaper and re-apply via
`SystemParametersInfo`.
- **Region authoring:** extract the label rectangles from `riojoy.xcf` into a
`regions.json`; in-app box editor for future tweaks.
- **Overlay generator — done ✅, verified on real assets.** `RioJoy.Core/Overlay`
is the pure, unit-tested layout engine: `FontFitter` is a faithful port of the
`calc-fontsize` auto-fit search (validated against a brute-force oracle),
`OverlayLayoutEngine` ports `create-data-layer`'s fit + horizontal/vertical
justification, and `OverlayTemplate`/`OverlayRegion` (a `regions.json` via
`OverlayTemplateStore`) hold the cell geometry/color. Label text is per-profile
(`RioProfile.OverlayLabels`); `GoobieDataImporter` reads the legacy `.data`
sheet into label rows. The rasterizer lives in `src/RioJoy.Overlay`
(**SkiaSharp**): `SkiaTextMeasurer` (shared with the engine so measured layout
== drawn output) + `SkiaOverlayRenderer` (draw labels → PNG). The full chain is
exercised end-to-end on the real cockpit art (`regions.json` + `riojoy.png` +
`TEST.data`) by `OverlayRenderIntegrationTests`. `RioJoy.Tray/WallpaperApplier`
applies the result via `SystemParametersInfo`.
- **Region authoring — extraction done ✅.** `tools/XcfRegionExtract` parses the
GIMP source (`riojoy.xcf`) and writes the 119-cell
`docs/reference/customBackground/regions.json` (per-layer offsets/size/font/color,
`BaseImagePath` → exported `riojoy.png`), anchored by `CockpitRegionsTests`.
⏳ Still to do: an in-app box editor for tweaks.
- **Runtime wiring — done ✅ (opt-in).** `RioJoy.Overlay/ProfileWallpaperGenerator`
renders a profile's labels onto the template base image; `RioCoordinator`
generates + applies the wallpaper on profile activation when
`AppConfig.OverlayTemplatePath` is set (best-effort, off by default, never breaks
activation). The live `SystemParametersInfo` apply changes a user setting, so it
is gated behind config and not exercised by tests. ⏳ Optional: restore the prior
wallpaper when going dormant.
- **Mapping editor — first cut done ✅.** `RioJoy.Tray/Editor/ProfileEditorForm`
shows the cockpit as a scrollable, clickable grid that mirrors the legacy
authoring spreadsheet's **logical** layout — parsed from the sheet's CSV export
(`docs/reference/customBackground/config-sheet.csv`) by `SheetLayout`, coloured
by section. (The layout deliberately follows the sheet, **not** the wallpaper
region positions: the wallpaper drives 6 displays via VGA chroma-channel
splitting, so its label positions stack and don't reflect the physical cockpit.)
Clicking an address cell edits its label and action/modifiers/lamp; the `iRIO`
word is read/written through `ButtonBinding``RioMapEntry.Create` (round-trip
tested) — no hex bit-twiddling. The value field is a **context-sensitive picker**:
keyboard actions pick a key by name (`KeyCatalog` VK names), joystick a Button N,
hat a direction, mouse/RIO-command the enum name; modifiers enable only for
keyboard. Opened from the tray ("Edit profile…"); Save persists the profile.
⏳ Still to refine: grouping a button's two bank addresses (edit once → both),
and clone-from-existing.
- The unified profile JSON supersedes both `RIO.ini` and the Google Sheet, with
importers for each.
- To confirm at Phase 7: target wallpaper resolution(s); static wallpaper vs.
@@ -0,0 +1,49 @@
"","","","","IMAGE NAME","","","","defalt","","","","Plasma greeting","","","","Hello,","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
"","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY","","S","C","A","KEY","S","","A","KEY","S","C","A","KEY","S","C","A","KEY","","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY",""
"","","","","G_KEY","","","","H_KEY","","","","I_KEY","","","","J_KEY","","","","","K_KEY","","","","L_KEY","","","","M_KEY","","","","N_KEY","","","","","O_KEY","","","","P_KEY","","","","Q_KEY","","","","R_KEY",""
"","","LABEL","","G","","LABEL","","H","","LABEL","","I","","LABEL","","J","","","LABEL","","K","","","","L","","LABEL","","M","","LABEL","","N","","","LABEL","","O","","LABEL","","P","","LABEL","","Q","","LABEL","","R",""
"","IsLit","","","2F","IsLit","","","2E","IsLit","","","2D","IsLit","","","2C","","IsLit","","","27","IsLit","","","26","IsLit","","","25","IsLit","","","24","","IsLit","","","37","IsLit","","","36","IsLit","","","35","IsLit","","","34",""
"","x","","","","x","","","","x","","","","x","","","","","x","","","","x","","","","x","","","","x","","","","","x","","","","x","","","","x","","","","x","","","",""
"","IsLit","","","2B","IsLit","","","2A","IsLit","","","29","IsLit","","","28","","IsLit","","","23","IsLit","","","22","IsLit","","","21","IsLit","","","20","","IsLit","","","33","IsLit","","","32","IsLit","","","31","IsLit","","","30",""
"","x","","","","x","","","","x","","","","x","","","","","x","","","","x","","","","x","","","","x","","","","","x","","","","x","","","","x","","","","x","","","",""
"","","LABEL","","S","","LABEL","","T","","LABEL","","U","","LABEL","","V","","","LABEL","","<","","","","^","","LABEL","","v","","LABEL","",">","","","LABEL","","W","","LABEL","","X","","LABEL","","Y","","LABEL","","Z",""
"","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY","","S","C","A","KEY","S","","A","KEY","S","C","A","KEY","S","C","A","KEY","","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY",""
"","","","","S_KEY","","","","T_KEY","","","","U_KEY","","","","V_KEY","","","","","LEFT","","","","UP","","","","DOWN","","","","RIGHT","","","","","W_KEY","","","","X_KEY","","","","Y_KEY","","","","Z_KEY",""
"","","","","KEYPAD","","","","LABELS","","","","JOYSTICK AIS","INVERT","","","","","S","C","A","KEY","KEY PAD","","","","BUTTONS","","","","S","C","A","KEY","","S","C","A","KEY","IsLit","","","THROTTLE BOARD","S","C","A","KEY","IsLit","","","JOYSTICK BOARD",""
"","","0","","0","","8","","8","","","","X","","","","","","","","","0_KEY","50","","","","58","","","","","","","8_KEY","","","","","MouseU","","","","38","","","","J1","","","","40",""
"","","1","","1","","9","","9","","","","Y","","","","","","","","","1_KEY","51","","","","59","","","","","","","9_KEY","","","","","MouseR","","","","39","","","","HatD","","","","41",""
"","","2","","2","","A","","A","","","","Z","","","","","","","","","2_KEY","52","","","","5A","","","","","","","A_KEY","","","","","MouseD","","","","3A","","","","HatU","","","","42",""
"","","3","","3","","B","","B","","","","R (L PEDDLE)","","","","","","","","","3_KEY","53","","","","5B","","","","","","","B_KEY","","","","","MouseL","","","","3B","","","","HatR","","","","43",""
"","","4","","4","","C","","C","","","","YR (R PEDDLE)","","","","","","","","","4_KEY","54","","","","5C","","","","","","","C_KEY","","","","","MouseLC","","","","3C","","","","HatL","","","","44",""
"","","5","","5","","D","","D","","","","ZR (RUDDER)","","","","","","","","","5_KEY","55","","","","5D","","","","","","","D_KEY","","","","","ESCAPE","x","","","3D","","","","J4","","","","45",""
"","","6","","6","","E","","E","","","","ZR (DISSABLE)","","","","","","","","","6_KEY","56","","","","5E","","","","","","","E_KEY","","","","","MouseRC","","","","3E","","","","J3","","","","46",""
"","","7","","7","","F","","F","","","","","","","","","","","","","7_KEY","57","","","","5F","","","","","","","F_KEY","","","","","J8","","","","3F","","","","J2","","","","47",""
"","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY","","S","C","A","KEY","IsLit","","","SECONDARY","IsLit","","","SCREEN","S","C","A","KEY","","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY",""
"","","","","HOME","","","","COMMA","","","","PERIOD","","","","END","","","","","MouseU","X","","","10","X","","","18","","","","RETURN","","X","","","LEFT","X","","","RIGHT","X","","","DOWN","X","x","x","UP",""
"","","LABEL","","TOP CONTACT","","LABEL","","UP CONTACT","","LABEL","","DOWN CON","","LABEL","","LAST CONTACT","","","","","MouseR","X","","","11","X","","","19","","","","MENU(ALT)","","","LABEL","","OFFENCE","","LABEL","","DEFENCE","","LABEL","","DRIVE","","LABEL","","BALANCE",""
"","IsLit","","","0F","IsLit","","","0E","IsLit","","","0D","IsLit","","","0C","","","","","MouseD","X","","","12","X","","","1A","","","","CONTROL","","IsLit","","","07","IsLit","","","06","IsLit","","","05","IsLit","","","04",""
"","X","","","","X","","","","X","","","","X","","","","","","","","MouseL","X","","","13","X","","","1B","","","","SHIFT","","x","","","","x","","","","x","","","","x","","","",""
"","IsLit","","","0B","IsLit","","","0A","IsLit","","","09","IsLit","","","08","","","","","MouseLC","X","","","14","X","","","1C","","","","VOLUME_UP","","IsLit","","","03","IsLit","","","02","IsLit","","","01","IsLit","","","00",""
"","X","","","","X","","","","X","","","","X","","","","","","","","TAB","X","","","15","X","","","1D","","","","VOLUME_DOWN","","x","","","","x","","","","x","","","","x","","","",""
"","","LABEL","","NEAR ENEMY","","LABEL","","NEXT ENEMY","","LABEL","","SUB TARGET","","LABEL","","LAST AGGESSOR","","","","","NULL","","","","16","","","","1E","","","","NULL","","","LABEL","","LDS","","LABEL","","UNDOCK","","LABEL","","ZOOM","","LABEL","","LSDI",""
"","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY","","","","","NULL","","","","17","","","","1F","","","","NULL","","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY","S","C","A","KEY",""
"","","","","R_KEY","","","","E_KEY","","","","Y_KEY","","","","Q_KEY","","","","","","","","","SECONDARY","","","","LABELS","","","","","","","","","L_KEY","","","","U_KEY","","","","Z_KEY","","","","I_KEY",""
"","","","","","","","","","","","","","","","","","","","","","","","10","","M U","","18","","ENTER","","","","","","","","","THROTTLE LABELS","","","","","","","","JOYSTICK LABELS","","","","",""
"","S","C","A","KEY","EXTERNAL KEY PAD","","","","BUTTONS","","","","S","C","A","KEY","","","","","","","11","","M R","","19","","ALT","","","","","","","38","","M ^","","","","","","40","","FIRE/ACCEPT","","","","",""
"","","","","RIO_AnalogAllReset","60","","","","68","","","","","","","RIO_AxesReadout","","","","","","","12","","M D","","1A","","CTRL","","","","","","","39","","M >","","","","","","41","","H v","","","","",""
"","","","","RIO_ResetThrottle","61","","","","69","","","","","","","RIO_FrequencyReadout","","","","","","","13","","M L","","1B","","SHIFT","","","","","","","3A","","M v","","","","","","42","","H ^","","","","",""
"","","","","RIO_ResetLeftPedal","62","","","","6A","","","","","","","RIO_more1","","","","","","","14","","MLC","","1C","","VL U","","","","","","","3B","","M <","","","","","","43","","H >","","","","",""
"","","","","RIO_ResetRightPedal","63","","","","6B","","","","","","","RIO_more2","","","","","","","15","","TAB","","1D","","VL D","","","","","","","3C","","ML","","","","","","44","","H <","","","","",""
"","","","","RIO_ResetVerticalJoystick","64","","","","6C","","","","","","","RIO_more3","","","","","","","16","","","","1E","","","","","","","","","3D","","ESC","","","","","","45","","NEXT PRIMEARY","","","","",""
"","","","","RIO_ResetHorizontalJoystick","65","","","","6D","","","","","","","RIO_more4","","","","","","","17","","","","1F","","","","","","","","","3E","","MR","","","","","","46","","NEXT SECOND","","","","",""
"","","","","RIO_DigitalReset","66","","","","6E","","","","","","","RIO_more5","","","","","","","","","","","","","","","","","","","","3F","","REVERSE","","","","","","47","","TARGET/BACK","","","","",""
"","","","","RIO_StatusCheck","67","","","","6F","","","","","","","RIO_more6","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
"","","","","","","","","EXT KEYPAD","","","","LABLES","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
"","","","","","","0","","RIO_0","","8","","RIO_8","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
"","","","","","","1","","RIO_1","","9","","RIO_9","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
"","","","","","","2","","RIO_2","","A","","RIO_A","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
"","","","","","","3","","RIO_3","","B","","RIO_B","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
"","","","","","","4","","RIO_4","","C","","RIO_C","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
"","","","","","","5","","RIO_5","","D","","RIO_D","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
"","","","","","","6","","RIO_6","","E","","RIO_E","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
"","","","","","","7","","RIO_7","","F","","RIO_F","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
1 IMAGE NAME defalt Plasma greeting Hello,
2 S C A KEY S C A KEY S C A KEY S C A KEY S C A KEY S A KEY S C A KEY S C A KEY S C A KEY S C A KEY S C A KEY S C A KEY
3 G_KEY H_KEY I_KEY J_KEY K_KEY L_KEY M_KEY N_KEY O_KEY P_KEY Q_KEY R_KEY
4 LABEL G LABEL H LABEL I LABEL J LABEL K L LABEL M LABEL N LABEL O LABEL P LABEL Q LABEL R
5 IsLit 2F IsLit 2E IsLit 2D IsLit 2C IsLit 27 IsLit 26 IsLit 25 IsLit 24 IsLit 37 IsLit 36 IsLit 35 IsLit 34
6 x x x x x x x x x x x x
7 IsLit 2B IsLit 2A IsLit 29 IsLit 28 IsLit 23 IsLit 22 IsLit 21 IsLit 20 IsLit 33 IsLit 32 IsLit 31 IsLit 30
8 x x x x x x x x x x x x
9 LABEL S LABEL T LABEL U LABEL V LABEL < ^ LABEL v LABEL > LABEL W LABEL X LABEL Y LABEL Z
10 S C A KEY S C A KEY S C A KEY S C A KEY S C A KEY S A KEY S C A KEY S C A KEY S C A KEY S C A KEY S C A KEY S C A KEY
11 S_KEY T_KEY U_KEY V_KEY LEFT UP DOWN RIGHT W_KEY X_KEY Y_KEY Z_KEY
12 KEYPAD LABELS JOYSTICK AIS INVERT S C A KEY KEY PAD BUTTONS S C A KEY S C A KEY IsLit THROTTLE BOARD S C A KEY IsLit JOYSTICK BOARD
13 0 0 8 8 X 0_KEY 50 58 8_KEY MouseU 38 J1 40
14 1 1 9 9 Y 1_KEY 51 59 9_KEY MouseR 39 HatD 41
15 2 2 A A Z 2_KEY 52 5A A_KEY MouseD 3A HatU 42
16 3 3 B B R (L PEDDLE) 3_KEY 53 5B B_KEY MouseL 3B HatR 43
17 4 4 C C YR (R PEDDLE) 4_KEY 54 5C C_KEY MouseLC 3C HatL 44
18 5 5 D D ZR (RUDDER) 5_KEY 55 5D D_KEY ESCAPE x 3D J4 45
19 6 6 E E ZR (DISSABLE) 6_KEY 56 5E E_KEY MouseRC 3E J3 46
20 7 7 F F 7_KEY 57 5F F_KEY J8 3F J2 47
21 S C A KEY S C A KEY S C A KEY S C A KEY S C A KEY IsLit SECONDARY IsLit SCREEN S C A KEY S C A KEY S C A KEY S C A KEY S C A KEY
22 HOME COMMA PERIOD END MouseU X 10 X 18 RETURN X LEFT X RIGHT X DOWN X x x UP
23 LABEL TOP CONTACT LABEL UP CONTACT LABEL DOWN CON LABEL LAST CONTACT MouseR X 11 X 19 MENU(ALT) LABEL OFFENCE LABEL DEFENCE LABEL DRIVE LABEL BALANCE
24 IsLit 0F IsLit 0E IsLit 0D IsLit 0C MouseD X 12 X 1A CONTROL IsLit 07 IsLit 06 IsLit 05 IsLit 04
25 X X X X MouseL X 13 X 1B SHIFT x x x x
26 IsLit 0B IsLit 0A IsLit 09 IsLit 08 MouseLC X 14 X 1C VOLUME_UP IsLit 03 IsLit 02 IsLit 01 IsLit 00
27 X X X X TAB X 15 X 1D VOLUME_DOWN x x x x
28 LABEL NEAR ENEMY LABEL NEXT ENEMY LABEL SUB TARGET LABEL LAST AGGESSOR NULL 16 1E NULL LABEL LDS LABEL UNDOCK LABEL ZOOM LABEL LSDI
29 S C A KEY S C A KEY S C A KEY S C A KEY NULL 17 1F NULL S C A KEY S C A KEY S C A KEY S C A KEY
30 R_KEY E_KEY Y_KEY Q_KEY SECONDARY LABELS L_KEY U_KEY Z_KEY I_KEY
31 10 M U 18 ENTER THROTTLE LABELS JOYSTICK LABELS
32 S C A KEY EXTERNAL KEY PAD BUTTONS S C A KEY 11 M R 19 ALT 38 M ^ 40 FIRE/ACCEPT
33 RIO_AnalogAllReset 60 68 RIO_AxesReadout 12 M D 1A CTRL 39 M > 41 H v
34 RIO_ResetThrottle 61 69 RIO_FrequencyReadout 13 M L 1B SHIFT 3A M v 42 H ^
35 RIO_ResetLeftPedal 62 6A RIO_more1 14 MLC 1C VL U 3B M < 43 H >
36 RIO_ResetRightPedal 63 6B RIO_more2 15 TAB 1D VL D 3C ML 44 H <
37 RIO_ResetVerticalJoystick 64 6C RIO_more3 16 1E 3D ESC 45 NEXT PRIMEARY
38 RIO_ResetHorizontalJoystick 65 6D RIO_more4 17 1F 3E MR 46 NEXT SECOND
39 RIO_DigitalReset 66 6E RIO_more5 3F REVERSE 47 TARGET/BACK
40 RIO_StatusCheck 67 6F RIO_more6
41 EXT KEYPAD LABLES
42 0 RIO_0 8 RIO_8
43 1 RIO_1 9 RIO_9
44 2 RIO_2 A RIO_A
45 3 RIO_3 B RIO_B
46 4 RIO_4 C RIO_C
47 5 RIO_5 D RIO_D
48 6 RIO_6 E RIO_E
49 7 RIO_7 F RIO_F
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB