Project: SC Signature Scanner
Location: C:\Users\larse\PycharmProjects\AREA52\SC_Signature_Scanner\
Developer: Mallachi
Current Version: v4.2.1 — Released
Development Period: January 8, 2026 - ongoing
The SC Signature Scanner is a real-time target identification tool for Star Citizen. It monitors screenshots and uses OCR to detect signature values from the in-game HUD, then matches them against a database to identify asteroids, deposits, and salvage targets.
The development log shall serve as the authoritative project state document. It must be complete enough that any AI can read it and immediately understand: (a) current project status, (b) what has been implemented, (c) what remains to be done, (d) why key decisions were made.
At the start of each development session, Claude shall review previous chat history to identify and document any unlogged events, decisions, or changes before proceeding with new work.
At session end, if substantial work was completed, the devlog shall be updated with: work completed, problems encountered and solutions, any new decisions or deferrals, and updated status of pending items.
Technical decisions shall be recorded with rationale. "We chose X" is insufficient - "We chose X because Y, and rejected Z because W" enables future AI to understand context and avoid revisiting settled questions.
The devlog shall always contain a clear "Current Status" or "Next Steps" section so any AI knows exactly where to resume work.
- Screenshot folder monitoring with automatic signature detection
- OCR-based signature value extraction from game HUD
- Database matching for asteroids, surface deposits, ground deposits, salvage, and wreck debris
- Tobii Eye Tracker 5 integration (optional, deferred)
- Manual scan region configuration (fallback)
Changes after initial v4.2.1 release:
overlay.py: Target name in popup header now always green (#3fb950)overlay.py: Removed redundant "Dominant mineral:" label (name already shown in header)main.py: Test popup updated to SC 4.7 example — Torite (Uncommon) sig 3900main.py: Added memorial label in header: "✦ In memory of Regolith.Rocks — The Industrial Community"build.py: FixedUnicodeEncodeErrorcrash on Windows CP1252 console — addedsys.stdout.reconfigure(encoding='utf-8')at startupbuild.py: Removed stale Regolith API references from runtime file summary
Released: v4.2.1 pushed to GitHub, exe attached to release.
In-game testing revealed the overlay was displaying "100% pure mineral: Torite" for ship mining matches. PTU composition data (mining_data-4.7.0-ptu.11450623.json) confirmed rocks have a dominant mineral (40–80%) plus secondary minerals (5–20%) — they are NOT guaranteed 100% pure.
Changes made to overlay.py:
- Ship mining confirmed mineral label:
"100% pure mineral:"→"Dominant mineral:" - Ground deposit small method label:
"💎 Hand Mining (100% single mineral)"→"💎 Hand Mining" - Ground deposit large method label:
"🚗 ROC Mining (100% single mineral)"→"🚗 ROC Mining" - Ground deposit unknown mineral list label:
"100% purity - one of:"→"Possible mineral:"
Also added in this session:
SignatureValue.md: Full rewrite for SC 4.7. Per-mineral signature system documented with secondary mineral columns from PTU data. Old I/C/S/P/M/Q/E content removed.data/mining_data-4.7.0-ptu.11450623.json: PTU composition source file added to data folder.combat_analyst_db.json:compositionand_descriptionfields updated to reflect dominant mineral language.TODO.md: Added Windows OCR (WinRT) investigation item; added deferred ship ID feature entry.ship_scan_test.md: Data collection template for empirical ship CS scanning (deferred pending SC scanner rework).
Note: Ground deposits are still 100% single-mineral per cluster — the cluster rules are accurate. The correction applies only to ship-mining rocks which have mixed composition.
SC 4.7 deposits are 100% single-mineral per cluster (no mixed composition), making value estimation from composition data unnecessary. The Regolith.rocks API and UEX pricing integrations were removed entirely.
Removed from main.py:
row3UI block: REFINERY METHOD dropdown + DATA SOURCES status panel- 12 methods:
_init_pricing,_on_method_changed,_get_current_yield,_refresh_pricing,_change_api_key,_refresh_all_data,_update_api_status,_update_pricing_status,_validate_api_key_startup,_validate_key_with_retry,_check_regolith_cache,_show_api_key_dialog - Startup API key validation gate
- Config load/save:
refinery_methodfield import time(only used in retry method)
Removed from scanner.py (done in prior session): import pricing, _get_rock_value_and_composition, est_value/composition fields from matches.
Removed from overlay.py (done in prior session): est_value display, composition table, est_price_per_scu.
Note: pricing.py and regolith_api.py kept on disk but no longer imported anywhere.
SC 4.7 added new salvage gameplay with sized wreck debris entities that have distinct signatures.
New salvage signatures extracted from Game2.xml:
- 1700 = Small Wreck Debris (Avenger-class hull pieces + scrap cargo containers)
- 1850 = Medium Wreck Debris (Ares Inferno-class hull pieces)
- 2000 = Salvage Panels / FPS Active Scrap (unchanged)
- 2400 = Large Wreck Debris (C2 Hercules-class hull pieces)
- 3000 = Capital Wreck Debris (890 Jump-class hull pieces) — COLLISION with FPS ground deposit small
New collision noted: 3000 now collides between FPS small ground deposits and 890 Jump capital wreck debris. Both matches will be shown when 3000 is scanned. Context-dependent (space = likely debris, planet = likely ground deposit).
Changes made:
combat_analyst_db.json: Updatedsalvagesection to new structure (panels + debris dict). Added 1700, 1850, 2400 tosignature_lookup. Updated 3000 entry with collision note.scanner.py:_build_lookups: Loadssalvage.panels._base_signatureand allsalvage.debrisentries intosalvage_debris_typeslist. All debris sigs added toknown_base_signaturesfor OCR correction.scanner.py:match_signature: Added debris check loop after panels check. Producessalvage_debristype matches.overlay.py: Addedsalvage_debrishandling — screwdriver icon, "Wreck Debris — Tractor Beam / Collect" method label.main.py: About tab updated with full salvage signature table.version_checker.py: Bumped to v4.1.0.clean.py/build.py: Updated shebangs topython, added Python 3.13 guard in build, tool cache cleanup,nulartifact cleanup..gitignore: Rewritten UTF-8, added tool caches,nul, data cache files.
Also investigated (no changes): Ship cross-section signatures — confirmed standardised per model (3D vector, not a single HUD value, dynamic — not suitable for static lookup).
The SC 4.7 mining system is completely different from 4.6.
The old I/C/S/P/M/Q/E asteroid type system is REMOVED in SC 4.7. The new system uses per-mineral signatures: each mineral has a unique signature value that directly identifies it, whether it appears in an asteroid or a surface rock.
New signature architecture (SC 4.7):
- Legendary tier (3170-3200): Quantainium, Stileron, Savrilium
- Epic tier (3370-3400): Ouratite, Riccite, Lindinium
- Rare tier (3540-3600): Beryl, Taranite, Borase, Gold, Bexalite
- Uncommon tier (3825-3900): Laranite, Aslarite, Titanium, Tungsten, Agricium, Torite
- Common tier (4180-4300): Hephaestanite, Tin, Quartz, Corundum, Copper, Silicon, Iron, Aluminum, Ice
- Ground FPS (3000) and GV/ROC (4000) unchanged
- Salvage (2000) unchanged
Changes made:
combat_analyst_db.json: Complete restructure. Removedspace_deposits,surface_deposits,rare_asteroids. Newship_miningsection with tiered mineral entries.scanner.py:_build_lookups: Now reads tiered mineral structure. Each sig maps directly to a known mineral.scanner.py:match_signature: Ship-mining matches now includemineral,tier, and per-SCU price. No Regolith composition lookup needed (rock is 100% single mineral).overlay.py: Newship_miningcategory handling with tier-based colour coding (red=legendary/epic, purple=rare, orange=uncommon, grey=common). Confirmed mineral shown definitively, not as a "possible list".main.py: About tab updated to show new tier ranges.- Version: 3.5.0 → 4.0.0
Version 4.0.0 rationale: Major breaking change — all old type-based signatures (4700-4900) are invalid in SC 4.7.
Source: Game2.xml extracted via unp4k-suite v3.13.66 from SC 4.7 Data.p4k
C-1 resolved: Ground deposit large (ROC/GV) base signature was incorrectly 3000 in the DB. Confirmed via 4.7 DCB as 4000. Updated combat_analyst_db.json and scanner.py fallback defaults.
All existing values confirmed unchanged in SC 4.7:
- Space: I=4000, C=4700, S=4720, P=4750, M=4850, Q=4870, E=4900
- Surface deposits: 4000 (all types)
- FPS small ground: 3000
- Salvage panels: 2000
NEW — Rare asteroid mineral variants (not in previous DB):
- Beryl: 3540, Taranite: 3555, Borase: 3570, Gold: 3585, Bexalite: 3600
- These have unique sub-4000 signatures distinguishable from standard types
NEW — Undetectable items confirmed:
- Vlk Pearls, Vlk Irradiated Pearls, Flowstone = signature 0
NEW — Ground deposit minerals:
- Added Sadaryx, Janalite, Saldynium, Carinite to minerals list (found in DCB, not in previous survey)
L-1 fixed: About tab now shows Small (3000) and Large (4000) instead of stale 120/620 values.
Version bumped: 3.4.0 → 3.5.0
Files changed: data/combat_analyst_db.json, scanner.py, main.py, version_checker.py, TODO.md
Batch fix for all findings from code_review.md that are independent of the C-1 signature value verification.
H-1 — Bare except: blocks → except tk.TclError:
overlay.py: 5 occurrences inshow(),_hide(),destroy()teardown pathssplash.py: 2 occurrences inpump()andclose()
H-3 — os.system shell injection → subprocess.run
main.py:_open_debug_folder: macOS and Linux paths now use list-form subprocess, bypassing shell
H-4 — Triple Regolith API call reduced to one
regolith_api.py:fetch_all_data: singlefetch_survey_datacall, loop over response keys- Error now stored in
result["_rock_composition_error"]instead of silently discarded
H-5 — time.sleep(3) on main thread → event-loop pump
main.py:_validate_key_with_retry: replaced with a 3-second deadline loop callingroot.update()every 50ms — UI stays responsive during retry wait
L-6 — os._exit(0) → sys.exit(0)
main.py:exit_and_download: replacedos._exit(bypasses cleanup) withroot.quit()+sys.exit(0)
M-3 — OverlayPopup second tk.Tk() eliminated
overlay.py: constructor now acceptsroot: tk.Tk; no longer creates its own hidden rootmain.py: all three call sites updated to passroot=self.rootdestroy()no longer callsself._root.destroy()(does not own the root)
M-2 — Config.get() repeated file reads → in-memory cache
config.py: addedself._cache;load()returns cached copy on repeat calls;save()updates cache
M-5 — Config and region paths now use paths.get_user_data_path()
config.py: default config path nowpaths.get_user_data_path() / "config.json"region_selector.py:CONFIG_FILEnowpaths.get_user_data_path() / "scan_region.json"- Both configs now persist correctly in PyInstaller frozen builds
M-4 — PricingManager data dir default fixed
pricing.py: defaultdata_dirnowpaths.get_user_data_path() / "data"; UEX cache persists across frozen exe restarts
M-6 — Singleton race condition in regolith_api.get_api()
regolith_api.py: addedthreading.Lock()guarding_instancecreation
M-7 — O(n) list dedup in _extract_signatures → O(1) set
scanner.py: replacedraw_valueslist membership check with aseen: set[int]
M-8 — Type annotation corrections
scanner.py:Optional[callable]→Optional[Callable[[], None]]for download callbacksscanner.py:output_dir: Path = None→output_dir: Optional[Path] = None
L-4 — Hot-path import cv2 inside methods → module-level
scanner.py:cv2now imported at module level withHAS_CV2flag; inline imports removed
CURRENT_EPOCH updated
regolith_api.py:"4.4"→"4.6"to match app version and database
Files changed: main.py, overlay.py, splash.py, regolith_api.py, config.py, region_selector.py, pricing.py, scanner.py
Problem: _on_new_screenshot is called by the watchdog file monitor on a background thread.
Multiple calls to self._log() (modifying a tk.Text widget) and self.stats_label.configure()
were made directly from that thread. Tkinter is not thread-safe on Windows; these off-thread widget
calls cause intermittent UI corruption and crashes during active screenshot scanning.
Fix: Refactored _on_new_screenshot so the OCR scan (scanner.scan_image) continues running
on the background thread (it is the expensive work and must not block the main loop), but all
collected log lines, the stats counter increment, and any overlay display are dispatched to the
main thread in a single self.root.after(0, _ui_update) call. The overlay display was already
correctly deferred — this fix makes the log and stats consistent with that pattern.
Files: main.py:1285–1340
Initial Concept: The project originated from an idea to enhance Wingman AI (a Star Citizen AI assistant) with Tobii Eye Tracker integration. The concept was to allow players to look at something in-game and ask "What is that?" with the AI analyzing the focused area.
Key Decisions:
- Standalone tool rather than Wingman AI skill (simpler distribution)
- Screenshot-based capture (using SC's native screenshot function)
- Folder monitoring approach (watchdog library)
- Overlay popup for results display
Project Structure Created:
SC_Signature_Scanner/
├── main.py # Main application with tkinter UI
├── scanner.py # OCR and signature matching
├── overlay.py # Popup overlay display
├── monitor.py # Screenshot folder watcher
├── config.py # Configuration management
├── clean.py # Cache cleanup utility
├── requirements.txt # Python dependencies
└── data/
└── combat_analyst_db.json # Signature database
Data.p4k Mining:
Used scdatatools and unp4k to extract signature data directly from Star Citizen's game files. This provided:
- Ship cross-section dimensions (CS values)
- Asteroid type signatures
- Deposit signatures
- Mining rock compositions
Key Discovery - Signature Formula:
Total Signature = Count × Base Signature
Example: Signature 3400 = 2× C-type asteroids (base 1700 each)
Database Version 4.0 Created:
| Category | Types | Signature Range |
|---|---|---|
| Space Deposits (Asteroids) | I, C, S, P, M, Q, E | 1660-1900 |
| Surface Deposits | Shale, Felsic, Obsidian, Atacamite, Quartzite, Gneiss, Granite, Igneous | 1730-1950 |
| Ground Deposits (Small) | FPS/Hand mining | 120 base |
| Ground Deposits (Large) | ROC/Vehicle mining | 620 base |
| Salvage | Per panel | 2000 base |
Attempt 1: Naive OCR
- Simple text search for "SIG:" label
- Failed: Label not always present, position varies
Attempt 2: Gradient Bar Detection
- Find two vertical gradient bars (always present when scanning)
- Calculate bar angle → rotate image to vertical
- Signature position = midpoint between bar tops
- Problem: Angle calculation returned -178.8° (picking up wrong elements)
Attempt 3: Icon Triangle Detection
- Find cone icon (left) and signal icon (right)
- Calculate equilateral triangle
- OCR at apex
- Problem: Too many similar-colored elements causing false matches
Attempt 4: HUD Circle Detection
- Find the targeting reticle using color saturation + Hough circles
- Calculate signature position relative to circle center
- Problem: Complex, unreliable across different HUD palettes
Final Solution: Fixed Region + Manual Calibration
- User defines scan region once via GUI tool
- OCR that fixed region on every screenshot
- Simple, reliable, works across all HUD styles
UEX Corp API Integration:
- Fetches live ore prices from
api.uexcorp.uk - 30-minute cache TTL
- Calculates estimated rock values using:
- Rock composition data (from Regolith.rocks)
- Current ore prices (from UEX)
- Refinery yield setting (user configurable)
Value Calculation Formula:
mineral_mass = deposit_mass × mineral_percentage
mineral_volume = mineral_mass / density
value = mineral_volume × price × refinery_yield
Mineral Composition Display: Each rock type now shows probable mineral spawns with:
- Spawn probability (%)
- Median percentage when present
- Individual mineral value
- Price per SCU
Research Phase:
- Tobii Eye Tracker 5 (consumer) has no official SDK
- Tobii 5L (commercial) requires €1495/year license
- Solution: PyEyetracker project (Apache-2.0 license)
Implementation:
- GazeServer.exe provides WebSocket interface on localhost:8765
- Returns gaze coordinates in normalized (0-1) format
- SC Signature Scanner connects and converts to pixel coordinates
Tobii Tab Features:
- Connection status indicator
- Download button for GazeServer.exe
- Test connection functionality
- Automatic fallback to fixed region if Tobii unavailable
Decision (January 12): Tobii support removed from v1.1.0 release - too complex for initial tester distribution. Fixed region approach is sufficient. Tobii can be re-added later.
Theme: Regolith.rocks Inspired
- Dark background (#1a1a2e)
- Orange accent (#f4a259)
- Cyan success (#4ecca3)
- Professional mining tool aesthetic
Main Window Tabs:
- Scanner - Start/stop monitoring, activity log, results display
- Settings - Screenshot folder, overlay options, debug mode, pricing
- Tobii Tracker - Connection status, region configuration
- About - Version info, credits
Region Selector Tool:
- Opens fullscreen with screenshot
- Click and drag to define scan region
- Escape to cancel
- Save/Clear/Cancel buttons
Partnership: Collaboration with Regolith.rocks team for:
- Rock composition survey data
- Mining location bonuses
- Authoritative mineral spawn rates
API Features:
- API key authentication (required)
- Profile validation on startup
- Rock composition queries per system
- Local cache with manual refresh
Startup Flow:
- Check for saved API key
- Validate against Regolith.rocks
- If invalid → prompt for new key
- If user cancels → exit app
- Cache composition data locally
Problem Identified: Original OCR pipeline was over-processing images:
- Grayscale conversion (lost orange color info)
- Fixed threshold at 80 (caught background noise)
- Binary output (destroyed anti-aliasing)
- 4x upscale on binary (blocky artifacts)
Result: "1,850" read as "1950"
Solution: Hybrid OCR Mode
Mode 1: Raw (Minimal Processing)
- Just grayscale conversion
- Preserves anti-aliasing
- Better for clean HUD text
Mode 2: Adaptive (OpenCV)
- Adaptive thresholding with Gaussian method
- Handles uneven backgrounds
- Better for cluttered scenes
Mode 3: Hybrid (Default)
- Try raw first
- If no signatures found, try adaptive
- Best of both worlds
Implementation:
self.ocr_mode = 'hybrid' # Options: 'raw', 'adaptive', 'hybrid'PyInstaller Configuration:
- Single-folder distribution
- Bundled database and assets
- Hidden imports handled (cv2, scipy, etc.)
Build Output:
dist/SC_Signature_Scanner/
├── SC_Signature_Scanner.exe
├── data/
│ └── combat_analyst_db.json
└── [runtime dependencies]
Runtime Files (created on first use):
config.json- User settings + API keyscan_region.json- Defined scan regionSignatureScannerBugreport/- Debug output folder
Tester Distribution:
- Debug mode with timestamp-prefixed files
- Configurable debug output folder
- Clean.py utility for resetting state
Problem with Tesseract: The pytesseract/Tesseract OCR dependency was causing distribution headaches:
- External binary required (tesseract.exe)
- PATH configuration issues on user machines
- Inconsistent versions across installations
- Complex PyInstaller bundling
- Users reporting "tesseract not found" errors
Solution: EasyOCR Migrated to EasyOCR, a deep learning-based OCR engine:
- Pure Python package (pip install)
- No external binaries
- Models download automatically on first use (~115MB)
- Runs entirely offline after initial download
- Better accuracy on styled game text
Implementation Details:
| Component | Change |
|---|---|
scanner.py |
Complete rewrite of OCR pipeline |
requirements.txt |
Added easyocr, torch, torchvision; removed pytesseract |
SC_Signature_Scanner.spec |
Added EasyOCR hidden imports + data files |
Key Design Decisions:
-
Lazy Initialization: OCR reader created on first scan, not at startup
- Faster app launch
- Model download happens when actually needed
- UI can show progress during download
-
CPU-Only Mode:
gpu=Falseby default- Works on all machines
- Avoids CUDA dependency complexity
- GPU auto-detected if available
-
Digit Allowlist:
allowlist='0123456789,.'- Maximum accuracy for signature values
- Prevents letter/digit confusion (O vs 0, l vs 1)
-
Simplified Preprocessing:
- EasyOCR handles most preprocessing internally
- Only upscale small regions for better detection
- Removed complex threshold/binary conversion pipeline
Model Download Flow:
First OCR use:
1. Check ~/.EasyOCR/model/ for cached models
2. If missing, download from EasyOCR servers (~115MB)
3. Load models into memory
4. All subsequent runs use local cache
Files Modified:
scanner.py- New EasyOCR-based implementationrequirements.txt- Updated dependenciesSC_Signature_Scanner.spec- PyInstaller config for EasyOCR
Removed:
- Hybrid OCR mode (raw/adaptive) - no longer needed
- Complex image preprocessing pipeline
- Tesseract binary dependency
Remove ship signatures, consolidate signature data to single source of truth
- REMOVE: Ship radar cross-section data (252 ships) from
combat_analyst_db.json— unused dead data - REMOVE:
ship_lookupbuilder fromscanner.py— was building a lookup table that nothing consumed - REFACTOR: Consolidated signature values to single source of truth (
combat_analyst_db.json) - Removed hardcoded module-level constants:
KNOWN_BASE_SIGNATURES,ROCK_DISPLAY_NAMES,SIGNATURE_TO_ROCK_TYPE - All three are now derived from the JSON database in
_build_lookups() - Salvage
signature_per_panelnow read from JSON instead of hardcoded2000 - CLEANUP: Removed empty
_on_release()method and unused event binding inregion_selector.py - CLEANUP: Moved
import timefrom local scope to module level insplash.py - CLEANUP: Initialized
_test_overlayin__init__inmain.py, removedhasattrguard - RATIONALE: Single source of truth means updating signature values only requires editing the JSON file — no code changes needed
Signature value update for SC 4.5 + dead code cleanup
- UPDATE: All asteroid signature values updated (I-type 4000, C-type 4700, S-type 4720, P-type 4750, M-type 4850, Q-type 4870, E-type 4900)
- UPDATE: All surface deposit signatures now 4000 (CIG bug — collides with I-type Asteroid)
- UPDATE: Ground deposit signatures changed from 120/620 to 3000 for both variants (CIG bug)
- REMOVE: Surface deposit entries from SIGNATURE_TO_ROCK_TYPE — cannot map individually when all share 4000
- CLEANUP: Removed dead code:
_add_match_row()in overlay.py,_get_rock_value()in scanner.py - CLEANUP: Removed unnecessary import guards:
HAS_PRICING,HAS_REGION_SELECTOR(same-project modules, always present) - CLEANUP: Removed unused
get_release_notes()from version_checker.py - CLEANUP: Removed
packagingmodule fallback in version_checker.py — tuple comparison is sufficient - CLEANUP: Removed commented-out deferred dependencies from requirements.txt
- KNOWN ISSUE: Signature 4000 collision means scanner cannot distinguish I-type asteroids from surface deposits
- NOTE: Signature values may be corrected by CIG in SC 4.7 patch
UI improvements for refinery methods and tab styling
- IMPROVE: Refinery method dropdown now shows yield, speed, and cost info
- Format:
Dinyx Solventation (Yield 52.93% - Speed: Slowest - Price: Low$) - IMPROVE: Tab styling - selected tab now larger and bolder than unselected tabs
- Selected: 11pt bold with accent color; Unselected: 9pt regular with muted color
- DOCS: Updated claude.md with Regolith API refinery method documentation
Scipy bundling fix for PyInstaller
- FIX: Removed scipy excludes from PyInstaller spec - partial scipy exclusion breaks C extension imports
- ROOT CAUSE: EasyOCR requires scipy.ndimage, but excluding other scipy modules broke the shared binary loader
- NOTE: Build size will increase ~50-100MB but scipy now works correctly in frozen builds
EasyOCR type hint fix
- FIX: Changed type hints from
easyocr.ReadertoAnyin scanner.py - ROOT CAUSE: Type hints evaluate at class definition time; if import fails, the type hint crashes
Regolith API integration complete - Ready for testing
- FIX: pricing.py now reads rock compositions from Regolith cache (was looking for separate rock_types.json)
- CHANGE: Single source of truth - regolith_cache.json contains all rock composition data
- REMOVE: Dependency on static data/rock_types.json file
- FIX: Build script verification updated for PyInstaller _internal/ directory structure
- READY: Build complete, ready for testing and version control setup
- Initial tester release
- Fixed region scanning
- Basic OCR with threshold
- Pricing integration
- Regolith.rocks API
Display name improvements
- FIX: Asteroid display names now show full names ("C" → "C-type Asteroid")
- FIX: Added count suffix for multiples ("C-type Asteroid (x4)" for 4 asteroids)
- NOTE: Composition table requires Regolith cache (rock_types.json) - if missing, only basic info shown
Bug fixes for EasyOCR integration
- FIX: Pillow 10.0.0+ compatibility - added ANTIALIAS shim (EasyOCR uses deprecated constant)
- FIX: Overlay category mismatch - scanner returns
space_deposit/surface_deposit/ground_deposit, overlay was checking for old names (asteroid/deposit/fps_mining) - FIX: Ground deposit display now shows possible minerals list instead of "Unknown"
- IMPROVE: clean.py updated with
--ocrflag to optionally remove EasyOCR models (~115MB)
Major OCR engine migration
- BREAKING: Replaced pytesseract/Tesseract with EasyOCR (deep learning OCR)
- NEW: Automatic model download on first use (~115MB, then offline)
- NEW: Lazy OCR initialization (faster startup)
- NEW: UI callbacks for model download progress
- REMOVE: Hybrid OCR mode (no longer needed with EasyOCR)
- REMOVE: Tesseract binary dependency
- IMPROVE: Simplified image preprocessing pipeline
- IMPROVE: Digit allowlist for maximum signature accuracy
Designated for tester review before public release
- CHANGE: Startup order - API key validation now happens first, before loading signature database and pricing
- ADD: "Thanks To" section in About tab acknowledging testers
- FIX: About tab left panel background color (was light gray, now matches dark theme)
- IMPROVE: clean.py - now removes deprecated files automatically
- IMPROVE: build.py - added pre-build verification checks
- DOCS: Added Development Rules to DEVLOG for AI continuity
- DOCS: Added Current Status section to DEVLOG
- NEW: Hybrid OCR mode (raw + adaptive)
- FIX: OCR misreading digits (1850 → 1950)
- FIX: Region selector buttons accessibility in fullscreen
- ADD: OpenCV dependency for adaptive thresholding
- REMOVE: Tobii support (deferred to future release)
- IMPROVE: Debug output with per-mode images
| Decision | Rationale |
|---|---|
| Fixed region over auto-detection | Reliability across HUD variants |
| EasyOCR over Tesseract | No external binary, pure Python, better accuracy on game text |
| Regolith API mandatory | Ensures data quality, supports partner |
| Screenshot-based over live capture | Works with any display mode |
| Tkinter over Qt | Lighter weight, sufficient for needs |
| Local database over API-only | Offline capability, faster lookups |
| Lazy OCR init over eager | Faster startup, download only when needed |
| CPU-only OCR default | Universal compatibility, avoids CUDA complexity |
| Comma removed from OCR allowlist | Was causing misreads like "7,480" → "7,4480"; plain digit parsing is more reliable |
| Layer 3 signature validation | OCR reads commas/periods as digits; validation + correction against known bases fixes this |
| Morphological punctuation filtering | Commas/periods are ~5-20px vs digits 100+px; remove small connected components before OCR |
| Prefer lowest count in correction | 7400 = 4× M-type is more realistic than 7440 = 62× small ground deposit |
| Startup splash screen | Torch/EasyOCR takes 15-20s to load; users need visual feedback that app is working |
Use Any for easyocr type hints |
Type hints evaluate at class definition; if import fails, easyocr.Reader crashes |
| Full scipy bundling over partial | Excluding scipy submodules breaks C extension loader; ~50-100MB size increase is acceptable for reliability |
| JSON as single source of truth for signatures | Hardcoded Python constants duplicated JSON data and could drift; deriving from JSON means only one file to update |
- Tobii Eye Tracker integration
- Ship signature matching (removed in v3.4.0 — re-evaluate if needed)
- Auto-detection as fallback to fixed region
- Multi-monitor support testing
- Localization for non-English clients
- All signatures need re-verification after SC 4.7 patch (CIG may fix 4000 collision and ground deposit values)
- New deposit types may be added with SC patches
- Ship signatures removed in v3.4.0 — re-add if demand arises
| Dependency | Purpose | License |
|---|---|---|
| easyocr | Deep learning OCR engine | Apache 2.0 |
| torch | PyTorch (EasyOCR backend) | BSD |
| torchvision | PyTorch vision utilities | BSD |
| Pillow | Image processing | HPND |
| opencv-python | Image preprocessing | Apache 2.0 |
| watchdog | Folder monitoring | Apache 2.0 |
| requests | API calls | Apache 2.0 |
| numpy | Array operations | BSD |
Note: First run downloads ~115MB of EasyOCR model files to ~/.EasyOCR/model/. Subsequent runs are fully offline.
Status: v3.4.0 - Removed ship signatures, consolidated signature data to single source of truth
Immediate priorities:
Fix About tab background color issue✓ (completed Jan 14)Update clean.py and build.py✓ (completed Jan 14)Change startup order (API validation first)✓ (completed Jan 14)Add "Thanks To" section for testers✓ (completed Jan 14)Migrate from pytesseract to EasyOCR✓ (completed Jan 14)Fix Pillow ANTIALIAS compatibility✓ (completed Jan 14)Fix overlay category mismatch✓ (completed Jan 14)Fix asteroid display names✓ (completed Jan 14)Connect pricing.py to Regolith cache✓ (completed Jan 14)Fix build script for PyInstaller _internal/ structure✓ (completed Jan 14)Version control setup (GitHub)✓ (completed Jan 14)Fix OCR comma/period misreading✓ (completed Jan 15)Add startup splash screen✓ (completed Jan 15)Fix easyocr import NameError crash✓ (completed Jan 16)- Testing on fresh install
Blocking issues:
- Signature 4000 collision (I-type + all surface deposits) — CIG-side, awaiting SC 4.7 fix
Ready for: Fresh install testing, distribution to testers
Session Log - February 11, 2026 (Sessions 14-15): Game2.dcb Signature Extraction
Phase 1: P4K Search (Session 14)
- SC patch dropped today (Data.p4k grew ~1GB). Created
search_mining_data.pyto search for changed mining signature values. - Searched 1,287,040 files in Data.p4k: 11,710 mining-related files, 8,894 readable files extracted.
- FINDING: Mining signature values are NOT in loose XML/JSON files — compiled into
Game2.dcb(DataCore Binary, 298MB decompressed).
Phase 2: DCB Parsing (Session 15)
- Built custom Game2.dcb parser from scratch using StarBreaker C# source as reference.
- Key technical corrections from initial v1 parser:
- DataType enum values corrected (e.g., Single=0x0B not 0x0F)
- Struct/property names use string table 2, not table 1
- Value pool file order differs from header order (Boolean after UInt64)
- Record definitions are 32 bytes, not 36
- DataMapping-based offset calculation for data section
Phase 3: Signature Value Discovery
- Entity-to-signature chain traced through 4 struct layers:
- EntityClassDefinition → Components (StrongPointer array in strong pool)
- SSCSignatureSystemParams → radarProperties (inline StrongPointer @ byte 4)
- SSCRadarContactProperites → baseSignatureParams (inline StrongPointer @ byte 20)
- SSCSignatureSystemBaseSignatureParams → signatures (SimpleArray into Single pool)
- Signature value is at index 4 of an 8-element float32 array in the Single value pool.
- Key insight: BSP instances have ZERO StrongPointer pool entries (not accessed via pointers). They're accessed through inline StrongPointers in the struct data chain.
Phase 4: Results
- Successfully extracted signatures for 301 mineable/salvage entities.
- SPACE ASTEROIDS — ALL UNCHANGED:
- I=4000, C=4700, S=4720, P=4750, M=4850, Q=4870, E=4900
- SURFACE DEPOSITS — UNCHANGED: All types (Atacamite, Felsic, Gneiss, Granite, Igneous, Obsidian, Quartzite, Shale) = 4000
- FPS MINING ROCKS — UNCHANGED: All types (Hadanite, Dolivine, Aphorite, etc.) = 3000
- SALVAGE PANELS — UNCHANGED: SalvageLock/SalvageScrap = 2000
- CAVE DEPOSITS: 4000 (same as surface)
- ROC/GV MINING ROCKS — DISCREPANCY: All 6 GroundVehicle entities = 4000 (DB says 3000)
MineableRock_GroundVehicle_Carinite/Beradom/Feynmaline/Glacosite+ variants- Cannot determine if this changed in this patch or was always 4000
- Needs in-game verification
Additional Findings:
- Salvageable ship wrecks have varying signatures by hull size (1700-3000)
- Harvestable mineral pickups (1-hand) retain old signature of 120
- Flowstone and VlkMineablePearls have 0 signature (special items)
- 8-element signature array channels: [EM(?), IR(?), ?, ?, CrossSection, ?, ?, ?]
Scripts Created (in sc_data_extractor project):
parse_dcb_v2.py— Corrected DCB parser with StarBreaker-accurate formatextract_signatures.py— Targeted BSP instance extractiontrace_mining_signatures.py— Entity→component chain tracerdump_all_signatures.py— Full BSP instance dumpdebug_entity_mapping.py— Entity→BSP mapping diagnosticsdebug_bsp_refs.py— BSP reference mechanism discoveryextract_all_signatures.py— Final production extraction script
OUTPUT: extracted_shops/mining_signatures_extracted.json — complete entity-to-signature mapping
Session Log - February 6, 2026 (Session 13):
- REMOVE: Ship radar cross-section data (252 entries) from
combat_analyst_db.json— dead data, never used in matching - REMOVE:
ship_lookupbuilder inscanner.py— built a lookup table that was never queried - REFACTOR: Consolidated all signature values to single source of truth (
combat_analyst_db.json) - Removed
KNOWN_BASE_SIGNATURES,ROCK_DISPLAY_NAMES,SIGNATURE_TO_ROCK_TYPEmodule-level constants - Now derived dynamically from JSON in
_build_lookups() - Salvage per-panel value now read from JSON instead of hardcoded
- CLEANUP: Removed empty
_on_release()+ binding inregion_selector.py - CLEANUP: Moved
import timeto module level insplash.py - CLEANUP: Initialized
_test_overlayin__init__, simplified guard inmain.py - VERSION: Bumped to v3.4.0 (also fixed version_checker.py which was still at 3.2.0)
Session Log - February 6, 2026 (Session 12):
- UPDATE: All signature values updated for SC 4.5 game changes
- Asteroids: I=4000, C=4700, S=4720, P=4750, M=4850, Q=4870, E=4900
- Surface deposits: All types now 4000 (collides with I-type — CIG bug)
- Ground deposits: Both small and large now 3000 (were 120/620 — CIG bug)
- Updated both
scanner.pyconstants andcombat_analyst_db.json - CLEANUP: Removed dead code across codebase
overlay.py: Removed unused_add_match_row()(~85 lines)scanner.py: Removed unused_get_rock_value()(~11 lines)scanner.py: RemovedHAS_PRICING/HAS_REGION_SELECTORimport guards — direct imports for same-project modulesversion_checker.py: Removed unusedget_release_notes(), removedpackagingmodule fallbackrequirements.txt: Removed commented-out deferred dependencies (Tobii, systray, hotkeys)- NOTE: Signature values may be corrected in SC 4.7 — full re-verification needed when patch drops
Session Log - January 20, 2026 (Session 11):
- IMPROVE: Refinery method dropdown now displays yield, speed, and cost information
- Old format:
Dinyx Solventation (52.93%) - New format:
Dinyx Solventation (Yield 52.93% - Speed: Slowest - Price: Low$) - Widened combobox from 28 to 62 characters to fit new format
- IMPROVE: Tab styling updated - selected tab now visually larger than unselected
- Unselected tabs: 9pt font, muted color, less padding
- Selected tab: 11pt bold font, accent color, more padding
- DOCS: Reviewed and verified claude.md refinery method data against web sources
- Confirmed yield tiers, speed categories, and cost multipliers are accurate
- VERSION: Bumped to v3.2.0
Session Log - January 17, 2026 (Session 10):
- FEATURE: Added "Buy Me a Coffee" button to About tab
- Position: Below Signature Types in right column
- Includes flavor text explaining the software is free and inviting support
- Links to buymeacoffee.com/Mallachi
- Yellow button (#FFDD00) with coffee emoji, wider styling
- No version bump (v3.1.2 not yet released to testers)
Session Log - January 16, 2026 (Session 9):
- BUG REPORT: Tester error:
scipy install seems to be broken (extension modules cannot be imported) - ROOT CAUSE: PyInstaller spec excluded scipy modules to reduce build size, but partial exclusion breaks scipy's shared C extension loader
- FIX: Removed scipy excludes from SC_Signature_Scanner.spec - full scipy now bundled
- TRADE-OFF: Build size increases ~50-100MB, but scipy works correctly
- Bumped version to v3.1.2
Session Log - January 16, 2026 (Session 8):
- BUG REPORT: Tester crash on startup:
NameError: name 'easyocr' is not defined - ROOT CAUSE: Type hints
Optional[easyocr.Reader]evaluated at class definition time - When
import easyocrfails, the nameeasyocrdoesn't exist, so the type hint crashes - FIX: Changed type hints from
easyocr.ReadertoAnyin scanner.py - Affected:
self._ocr_readerattribute and_get_ocr_reader()return type - Now app loads even if easyocr import fails (shows proper error instead of crash)
- Bumped version to v3.1.1
Session Log - January 15, 2026 (Session 7):
- BUG: Overlay crash
TclError: bad screen distance "5 0"when showing ground deposit popup - ROOT CAUSE: Tkinter Label constructor doesn't accept tuple
pady=(5, 0)— only.pack()does - FIX: Moved tuple pady from Label constructor to
.pack(pady=(5, 0))in overlay.py - BUG: Signature correction picked wrong value:
74400→7440instead of7400 - ROOT CAUSE:
max(candidates)picked larger value; 7440 = 62× small ground (120) vs 7400 = 4× M-type (1850) - FIX: Changed
_try_correct_signature()to prefer lowest count:min(candidates, key=min_count) - IMPROVEMENT: Implemented morphological filtering to remove commas/periods BEFORE OCR
- RATIONALE: Commas are ~5-20 pixels, digits are 100+ pixels — size-based filtering is reliable
- NEW: Added
_remove_small_components()method using OpenCV connected components - Removes components < 50 pixels, fills with background color
- Debug mode saves
04a_removed_components.pngshowing removed pixels in red - BUG: 20-second startup with no feedback — users think app is frozen
- FIX: Added splash.py with animated loading screen shown immediately
- Status messages: "Loading core modules...", "Loading OCR engine...", "Loading UI components...", "Loading pricing data..."
- Splash closes before main window appears (only one Tk root allowed)
- TESTED: Comma filtering works —
7,400now correctly read as7400 - Bumped version to v3.1.0
Session Log - January 14, 2026 (Session 6):
- Investigated OCR failure:
7,480misread as7,4480→ parsed as[7448, 4480]→ no match - Root cause: Comma in allowlist causing EasyOCR to interpolate extra digits around comma position
- FIX: Removed comma from OCR allowlist (
'0123456789,.'→'0123456789.') - Pattern 2 in
_extract_signatureshandles plain digit sequences, so comma removal is safe - Tested with tighter scan region: OCR read
1850with 0.89 confidence ✓ - BUG: Threading crash when showing overlay - watchdog callback runs in background thread, Tkinter requires main thread
- FIX: Changed
overlay.show()to useroot.after(0, lambda: self._show_overlay(...))for thread-safe GUI update - Added
_show_overlay()helper method to main.py - BUG:
6.000parsed but returned empty (period pattern worked, but value not matched) - FIX: Added Pattern 2 for period-separated numbers (
\d{1,3}\.\d{3}) - BUG:
7,400read as74400(comma read as digit4when not in allowlist) - ROOT CAUSE: Both comma and period can be read as digits by OCR - no allowlist config solves this
- FIX: Implemented Layer 3 signature validation:
- Added
KNOWN_BASE_SIGNATURESconstant with all valid base values - Added
_is_exact_multiple()to check if value divides cleanly by any known base - Added
_try_correct_signature()to fix phantom digit insertion - Updated
_extract_signatures()to validate and auto-correct signatures
- Added
- Example:
74400→ not valid → try removing digits →7400÷ 1850 = 4 ✓ → corrected to 7400
Session Log - January 14, 2026 (Session 5):
- Identified disconnect: regolith_api.py saves to regolith_cache.json, pricing.py was loading from data/rock_types.json
- Fixed pricing.py to import regolith_api and read rock_compositions from cache
- Removed rock_types_file reference from PricingManager
- Fixed build.py verification path (PyInstaller now uses _internal/ subdirectory)
- Bumped version to v3.0.0
- Build successful, ready for testing
- Tested EasyOCR on full scan results panel (standalone test) - works but accuracy limited by image quality; signature scanner's focused region approach is better suited
- GIT: Pushed to GitHub - encountered 100MB file limit on dist zip (221MB)
- FIX: Rewrote git history to remove large files from commits (
git filter-branch) - FIX: Updated .gitignore to exclude build/, dist/, *.zip
- Successfully pushed v3.0.0 to GitHub
Session Log - January 14, 2026 (Session 4):
- Added ROCK_DISPLAY_NAMES mapping for short asteroid codes
- Scanner now shows "C-type Asteroid" instead of just "C"
- Added count suffix for multiples: "C-type Asteroid (x4)"
- Identified missing rock_types.json as cause of empty composition table
- Bumped version to v2.1.2
Session Log - January 14, 2026 (Session 3):
- Fixed Pillow 10.0.0+ compatibility (ANTIALIAS constant removed, added shim)
- Fixed overlay category mismatch (scanner uses space_deposit/surface_deposit/ground_deposit)
- Fixed ground deposit mineral display (shows possible_minerals list)
- Updated clean.py with --ocr flag and --help
- Bumped version to v2.1.1
Session Log - January 14, 2026 (Session 2):
- MAJOR: Migrated OCR engine from pytesseract to EasyOCR
- Rewrote scanner.py with EasyOCR implementation
- Updated requirements.txt (easyocr, torch, torchvision)
- Updated SC_Signature_Scanner.spec with EasyOCR hidden imports and data files
- Removed hybrid OCR mode (raw/adaptive) - no longer needed
- Added lazy OCR initialization with UI callback hooks
- Added digit allowlist for maximum signature accuracy
- Bumped version to v2.1.0 (Pre-release)
Session Log - January 14, 2026 (Session 1):
- Fixed About tab background color (missing bg parameter)
- Added Development Rules section to DEVLOG
- Added Current Status section to DEVLOG
- Updated clean.py: now removes deprecated files (hud_calibration.py, identifier_window.py, tobii_tracker.py)
- Updated build.py: added pre-build checks, better formatting, deprecated file warnings
- Changed startup order: API key validation now happens before signature database and pricing loads
- Added "Thanks To" section in About tab
- Bumped version to v2.0.0 (Pre-release)
- Designated v2.0.0 for tester review
- Developer: Mallachi
- Data Sources:
- Star Citizen game files (Data.p4k)
- UEX Corp API (pricing)
- Regolith.rocks (rock compositions)
- Inspiration: Wingman AI project
- Testing: Regolith.rocks community testers
Updated: January 15, 2026
SC_Signature_Scanner/
├── main.py # Main application, tkinter UI, startup flow
├── splash.py # Startup splash screen with loading status
├── scanner.py # EasyOCR engine, signature matching, component filtering
├── overlay.py # Results popup display, position adjuster
├── monitor.py # Screenshot folder watcher (watchdog)
├── config.py # Configuration persistence (JSON)
├── paths.py # Path utilities for frozen exe support
├── pricing.py # UEX API integration, value calculations
├── theme.py # RegolithTheme, UI colors/fonts
├── region_selector.py # Scan region definition tool
├── regolith_api.py # Regolith.rocks API client
├── version_checker.py # GitHub release checker
├── clean.py # Cache/pycache cleanup utility
├── build.py # PyInstaller build script
├── requirements.txt # Python dependencies
├── run_scanner.bat # Windows launch script
├── SC_Signature_Scanner.spec # PyInstaller spec file
├── README.md # User documentation
├── TODO.md # Signature database reference
├── DEVLOG.md # This file
├── data/
│ ├── combat_analyst_db.json # Signature database
│ └── uex_prices.json # UEX cache (runtime)
├── assets/ # UI assets (if any)
├── build/ # PyInstaller build output
├── dist/ # Distribution packages
└── screenshots/ # Test screenshots
Runtime files (created on first use):
config.json— User settings, API keyscan_region.json— Defined scan region coordinatesregolith_cache.json— Regolith.rocks rock composition data (in user data folder)SignatureScannerBugreport/— Debug output folder (configurable)
Document generated: January 12, 2026
Last updated: February 6, 2026 - v3.4.0 Remove ship signatures, consolidate to single source of truth