CPR-vCodex Steroids is a personal fork of CPR-vCodex that layers additional UI features, experimental subsystems, and distinct branding on top of the stable vCodex baseline. It targets the Xteink X4 (ESP32-C3) and maintains full compatibility with the vCodex reading analytics, highlights, dictionaries, and flashcards while adding a richer launcher, plugin system, and streaming statistics architecture.
Unlike the conservative vCodex approach of only carrying forward stable upstream changes, Steroids intentionally integrates larger architectural rewrites (streaming stats loader, Library V3 mixed view, declarative fast restart) and entirely new subsystems (Lua plugin VM, offline Wikipedia, screensaver) that are feature-complete but may carry higher merge risk. The firmware remains fast and stable for daily reading, with RAM/Flash budgets respected.
The philosophy: keep the vCodex reading experience intact, extend the device capabilities for power users.
Steroids branding: "CPR-vCodex Steroids" on boot, sleep, and web UI
| Feature | Description | Status |
|---|---|---|
| Steroids Branding | Custom 350×96 logo on boot/sleep; web UI (HomePage, Flash, Settings, Stats Editor); OTA points to marcoand75/cpr-vcodex-steroids |
✅ Complete |
| Library V3 | Mixed view (series tiles + standalone books); user collections (manual CRUD); auto series from EPUB calibre:series + folder fallback; case-insensitive natural sort; page frame cache |
✅ Complete |
| Reading Statistics (Streaming) | Incremental JSON loader (1 KB buffer); binary journal (reading_sessions.jrn, 32 B/record) for detached sessions; summary.json fast path (~6 KB) for Home/UI; import/export streaming (~20 KB peak RAM); lazy full-store load |
✅ Complete |
| Fast Restart (Standardized) | Declarative exitRestartPlan() per activity; ActivityManager::exitWithFastRestart(); RTC silent boot to Home; Reader/Library/Settings/Apps all seamless |
✅ Complete |
| Home Theme: Lyra Marcoand75 | Carousel with data panels (progress, time, sessions, reading days); frame cache; cover generation integration; summary.json fast path | ✅ Complete |
| Lua Plugin System | Lua 5.4 VM; plugin browser (/.crosspoint/plugins/); sandboxed cpr API (display, input, storage, books, stats); separate activity stack |
✅ Complete |
| Wikipedia Offline | ZIM/HTML article cache; full-text search; article rendering with images | ✅ Complete |
| Sleep Screen & Power Button | Modes: Off, Clock, Cover, Clock+Cover, Custom; cover filters (grayscale/inverted/sepia); short-press cycles mode; long-press sleep/power off | ✅ Complete |
| Screensaver | Idle-time animated: clock, bouncing logo, slideshow; separate from sleep screen; any input exits | ✅ Complete |
| Quick Cards | Card viewer for /cards/ on SD: image display (JPEG/PNG→BMP), QR code rendering (auto version), Code-128 barcode; structured parsing (WiFi, vCard, MeCard, Geo, phone, SMS, OTP/2FA, iCal event, URL) |
✅ Complete |
| Cover Generation Fixes | Corrupt BMP removal + retry; partial BMP protection during gen; cover refresh after delete; frame cache never stores placeholder | ✅ Complete |
| Settings Extensions | Library/Sleep/Power/Screensaver categories; web API batched JSON (<1s vs 50s); ISO code language persistence | ✅ Complete |
| i18n (24 Languages) | STR_STEROIDS, STR_CPR_VCODEX_STEROIDS added to all 24 language files |
✅ Complete |
| Shortcuts Registry (CTAD) | 15 shortcuts (Library, Settings, Apps, Favorites, Flashcards, Dictionary, File Transfer, Sleep, Quick Cards, Wikipedia, Plugins, Screensaver, Reading Stats, Bookmarks, Recent Books); null guard | ✅ Complete |
Steroids main interface: carousel, stats panels, and library view
Steroids Settings: Library, Sleep, Power Button, and Screensaver configuration
# Build default (X4/X3 ESP32-C3)
.\bin\build-vcodex.ps1
# Build release (gh_release)
.\bin\build-vcodex.ps1 -Environment gh_releaseArtifacts: artifacts/1.6.0.38.dev<N>-<sha>-cpr-vcodex-steroids.bin
Flash: Auto Flash page (X4 default, X4 Pro blocked)
OTA: https://github.com/marcoand75/cpr-vcodex-steroids/releases
Logo contributed by Which-Estimate4566.
My goal with this fork was to preserve CrossPoint experience while expanding the firmware around long-term reading engagement and personalization.
Unlike a complete rewrite, CPR-vCodex intentionally stays close to the upstream CrossPoint project and only carries forward additions or upstream changes that are stable and safe enough for daily reading.
Some of the main additions include:
- full reading analytics: reading stats, heatmaps, day detail, reading profile, session history, goals, streaks, and achievements
- Sync Day support for reliable offline day-based statistics on hardware without a trustworthy sleep RTC
- per-book statistics tools, including reading-time correction, start-date editing, and per-book stats reset
- StarDict dictionary support from the SD card, with selectable monolingual and translation dictionaries, per-language folders, reader word lookup, suggestions, and lookup history
- offline Flashcards with CSV decks, multiple study modes, recents, stats, and session summaries
- unified EPUB Highlights for selected text and saved pages, with a global Highlights app and backward-compatible bookmark storage
- repagination-resistant EPUB page marks and highlights, stored with visible-text anchors in BookmarkStore v5 while retaining v1-v4 migration
- highlight matching that survives layout-inserted hyphens, split ellipses, and non-breaking-space fragments without confusing authored hyphens
- customizable Home and Apps shortcuts, reader quick settings, reading layouts, themes, and Lyra Carousel workflow improvements
- enhanced sleep tools, including custom image directories, cover/custom stats screens, sleep previews, cached sleep frames, and configurable clean sleep refresh
- downloadable and manually installable SD-card fonts, including vCodex families such as
ChareInkandLexend - improved EPUB image handling for packed low-depth PNGs, scaled images and SVG image references, with low-memory band rendering and decode placeholders
- native EPUB ruby annotations for Chinese/Japanese reading aids, improved CJK line breaking, and SD-font CJK fallback for book lists and chapter titles
- Screen Clean, SD firmware update, Auto Flash, reading stats editor, and other maintenance/workflow utilities
- named KOReader Sync profiles with optional metadata, ask/smart synchronization behavior and per-profile account registration
- OPDS filename options, reader refresh controls, Bionic Reading, text darkness, dark mode, and other reader quality-of-life settings
- carefully selected upstream CrossPoint improvements and fixes adapted without dropping vCodex-specific behavior
The philosophy of this fork is simple: keep the firmware fast, stable, and focused on reading, while making the device feel more rewarding and personal for people who read every day.
| Item | Value |
|---|---|
| Project | CPR-vCodex |
| Device | Xteink X4 (personally tested); Xteink X3 UC8253/UC8279d runtime support, with broader physical feedback requested. X4 Pro firmware distribution is withdrawn because locked devices do not have a confirmed recovery path. |
| Current release (CPR-vCodex) build | 1.6.0.37-cpr-vcodex |
| Release hardware stack | freeink-sdk cb9167d5, with runtime X3/X4 panel detection. |
| Latest SD font package | sd-fonts-m1-b4 |
| Changelog | CHANGELOG.md |
| Current release sync | CrossPoint Reader develop 233f93ff, including the FreeInkUI activity/input architecture, merged while retaining CPR-vCodex settings, statistics, bookmarks/highlights, dictionaries, themes, SD fonts, and release tooling. X4 Pro distribution remains withdrawn. |
| Current work | Stabilize X3/X4 OTA, language persistence, image allocation failures and sleep/wake. Audit and validation status. |
| Release validation | The .38 fix has passed update lookup, complete download, OTA installation and reboot on a USB-recoverable X4, plus USB image verification. Physical X3 validation remains pending. See the audit for the exact diagnostic build, target image and remaining checks. |
| Base firmware line | CrossPoint Reader 1.6.0 (upstream develop 233f93ff) |
| Latest references reviewed | CrossPoint aa994cf7, its allocation checks in 3555ff55, and CrossInk 7a092e88. Selected changes and exclusions are recorded in the stability audit. |
| Latest official commit incorporated | Release 1.6.0.31 adopted the FreeInkUI integration from PR #206, including freeink-sdk cb9167d5; X4 Pro distribution is now withdrawn. |
| Intentional upstream exclusions | Additional upstream device/theme variants remain outside the supported CPR-vCodex release targets unless explicitly documented. |
| Firmware targets | default/gh_release build the ESP32-C3 binary shared by X4 and X3 (runtime panel detection). Tags publish only <tag>.bin; X4 Pro release assets, OTA entries, and browser flashing are blocked. |
EPUB diagrams and gray backgrounds now retain their gray levels when text anti-aliasing is disabled (#215). Progressive JPEGs with separate component scans are also corrected using CrossPoint's #2925 fix. Existing image caches and settings remain valid. The image changes passed simulator regressions and tests against the actual JPEG decoder. The development build booted twice on X4; the two reported EPUBs still need visual confirmation on the physical screen.
CPR-vCodex 1.6.0.31 through 1.6.0.33 can find a new release but fail before receiving firmware bytes (#219). Version 1.6.0.37 still had a separate update-check failure: on X4, HTTPS certificate signature verification could run out of memory while Settings remained on the activity stack. Version 1.6.0.38 adapts CrossInk's fresh network boot: opening Update briefly shows Loading, then opens the updater with a clean heap and without SD reader fonts. It retains certificate verification. A successful check shows the installed and published versions; an equal or newer installed version is reported as up to date. A failed network or manifest check is reported separately and can be retried. The updater also retries the certificate-verified manifest through GitHub's raw host if Pages fails.
An installed updater cannot acquire a client-side fix through a download path
that consistently fails on that device. For an affected reader, the existing
alternative is to upload the published X3/X4 release BIN using
File Transfer > Join Network, then install it with
Settings > System > SD Card Firmware Update. Use the exact C3 release asset
and keep the reader powered throughout validation and installation. This path
does not require USB flashing or removing the microSD card.
Do not substitute an X4 Pro binary. X4 Pro distribution remains withdrawn.
Keep /.crosspoint (settings, progress and statistics) intact. A general
factory reset or downgrade is not the remedy for this transport failure.
The repaired updater obtains the expected SHA-256 over certificate-verified HTTPS and checks the downloaded size, digest, chip and image before selecting the inactive OTA partition. Automated fault-injection tests verify activation policy; they do not replace an end-to-end transfer and reboot on X3 and X4.
Some USB-locked Xteink X3 units with the newer UC8279d display controller appeared to remain frozen on the previous or Update Complete screen after installing older CPR-vCodex releases. The device was not actually bricked: the firmware continued running, but the unsupported display controller prevented the screen from refreshing.
Affected users have successfully recovered devices running CPR-vCodex 1.5.0.3 and 1.5.0.9 by blindly opening the SD firmware updater and installing 1.5.0.22, which detects both the original UC8253 and newer UC8279d X3 panels at boot.
Important
This emergency procedure is intended for an X3 whose display is already frozen on an older CPR-vCodex release. Do not use the blind sequence for a normally working device; use the visible Settings > System > SD Card Firmware Update flow instead. Back up the card first or use a separate clean FAT32 recovery card, and do not interrupt the device or remove the microSD while firmware validation or flashing is in progress.
- XTEINK X3 — vCodex Unfreeze procedure (PDF) consolidates the physical-button sequence, required waits, SD-card preparation, and final confirmation used for the successful recoveries.
- Froze in Update Complete (Soft Bricked?) — issue #193 contains the complete investigation and the step-by-step discussion with affected users, including their questions, screenshots, clarifications, and successful recovery reports.
- Auto Flash installs the latest CPR-vCodex firmware on the Xteink X4 and X3 from Chrome or Edge using Web Serial. X4 is always the default. X4 Pro remains visibly marked as withdrawn, but the page cannot select, download, or flash it—even if an obsolete manifest is cached.
- Reading Stats Editor edits exported reading stats locally in the browser. No upload, no server.
- Device web settings treat the KOReader password as write-only: the stored value is never returned to the browser, which only indicates that a password is already configured.
CPR-vCodex can use StarDict-format dictionaries stored on the microSD card. Dictionary data stays on the SD card; after a dictionary is selected, the firmware creates a small .cpridx cache next to it so later lookups stay fast.
Important: a loose .dict file is not enough. The dictionary must be a complete StarDict package with matching .ifo, .idx, and uncompressed .dict files using the same base filename.
Recommended microSD layout:
SD:/
dictionaries/
spanish/
es-es.ifo
es-es.idx
es-es.dict
es-es.syn # optional synonym/headword file
es-es.cpridx # generated by CPR-vCodex; do not copy manually
english-spanish/
en-es.ifo
en-es.idx
en-es.dict
Each language or dictionary group lives in dictionaries/<language>/. The directory name is the visible language/group label, so names such as spanish, english, english-spanish, or en-es are all valid. Each directory may contain one or more dictionaries.
The root folder is resolved case-insensitively, so /Dictionaries, /DICTIONARIES, and /dictionaries all work; CPR-vCodex keeps using the exact capitalization already present on the card.
For every StarDict dictionary, the required files are:
<name>.ifo: dictionary metadata, including name, word count, and format hints.<name>.idx: word index; it maps each headword to the byte offset of its definition.- uncompressed
<name>.dict: definition data.
Optional files:
<name>.synenables alternate headwords and synonym redirects when the dictionary provides them.<name>.cpridxis generated by CPR-vCodex after preparing the dictionary and should not be downloaded or copied by hand. *All files with the same name.
Compressed <name>.dict.dz dictionaries are detected but are not currently supported directly. If the downloaded package contains a .dict.dz file, open or extract it first and copy the resulting uncompressed .dict file to the SD card. The valid format for CPR-vCodex is .dict, not compressed .dict.dz.
Use on the Xteink:
- Copy the dictionary files to
dictionaries/<language>/on the microSD card. - Reinsert the card and open
Apps > Dictionary. - Choose the definition text size.
Mediumis the default. - Select the dictionary to prepare and activate it. Depending on the dictionary size, the first activation can take several seconds while CPR-vCodex builds its lookup cache.
- While reading an EPUB, open the reader menu to use
Look up word,Lookup history, orDictionaryto change the active dictionary/configuration and return to the book.
Dictionary download sources vary in quality, completeness, format, and license. Always extract the downloaded package until you have the .ifo, .idx, and .dict files, and check the license before redistributing a dictionary.
Monolingual (Defining) dictionary:
- Monolingual dictionaries adapted for CPR-vCodex includes several monolingual dictionaries adapted for cpr-vcodex.
Bilingual (Translation) dictionary:
- Bilingual dictionaries adapted for CPR-vCodex includes several bilingual dictionaries adapted for cpr-vcodex.
- WikDict StarDict downloads includes translation dictionaries such as German-English and English-German, depending on the published package. Includes several StarDict packages. Extract packages until you have matching
.ifo,.idx, and uncompressed.dictfiles.
If you know reliable public dictionary links for more languages, please contact the project or open an issue/discussion so this list can be updated.
CPR-vCodex supports extra .cpfont families stored on the microSD card. The built-in reader fonts still work as usual, and downloaded SD fonts such as Lexend appear in Settings > Reader > Font Family after the firmware discovers them.
Font discovery is lazy while the built-in font is selected, and the active SD font plus its catalog are released before Wi-Fi startup to leave more contiguous RAM for the radio. Both /.fonts and /fonts are resolved case-insensitively, including installs and deletion.
SD-card font rendering keeps a fast per-glyph advance cache when it is complete, and falls back to direct glyph measurement when an external font cache is missing an entry. Browser File Transfer downloads also preserve the advertised response size so downloaded files do not fail with content-length mismatch errors.
CJK-capable families can also provide 8, 10, and 12 pt files. CPR-vCodex uses those as size-matched fallbacks for Chinese, Japanese, and Korean text in the File Browser, Recent Books, and EPUB chapter list, and preloads each visible screen in one SD pass to avoid per-glyph reads.
The File Transfer EPUB optimizer includes an optional Remove embedded fonts advanced setting. It is off by default so the optimized book remains portable to readers that honor publisher fonts; enabling it removes font files, matching OPF/encryption entries, and @font-face rules because CPR-vCodex renders with its selected built-in or SD-card font.
Device download:
- Connect the reader to Wi-Fi.
- Open
Settings > Reader > Manage Fonts. - Select a family and download it.
- Return to
Reader Font Familyand choose the newly installed font.
Manual install from GitHub is faster when Wi-Fi on the device is slow. The CPR-vCodex package contains vCodex-specific additions; use the CrossPoint source/package for other common families:
- Download
all-fonts.zipfrom the latest CPR-vCodex SD font package. - Extract it into the root of the microSD card. The archive creates
fonts/<Family>/*.cpfont. - Reinsert the card, restart the device, and select the font under
Settings > Reader > Font Family.
Manual single-family install also works. Download all .cpfont files for a family from sd-fonts-m1-b4, create fonts/<Family>/ on the microSD card, and copy the matching files there.
Recommended microSD layout:
SD:/
fonts/
ChareInk/
ChareInk_12.cpfont
ChareInk_14.cpfont
ChareInk_16.cpfont
ChareInk_18.cpfont
Lexend/
Lexend_10.cpfont
Lexend_12.cpfont
Lexend_14.cpfont
Lexend_16.cpfont
Lexend_18.cpfont
Flashcards currently offers four review modes:
Due: builds a finite session from cards that are due first, then fills with unseen cards if needed.Session sizeis respected here, andAllmeans "all due cards plus unseen cards".Scheduled: builds a finite shuffled session from the whole deck.Session sizeis respected here, andAllmeans the whole deck.Infinite: ignoresSession size, keeps drawing cards from the whole deck, and never finishes on its own. Exit manually when you want the session summary.Sequential: uses every card in CSV order, ignoresSession size, and finishes after the last card.
Why it is split this way:
Study modedecides which cards enter the sessionSession sizedecides how many of those cards are included
Fail and Next send the current card back through the session flow. In Infinite, the queue is rebuilt again when a full pass is consumed, so practice can continue indefinitely. In Sequential, the deck is kept in file order.
Example CSV deck structure:
front,back
"What is the capital of France?","Paris"
"Who wrote Don Quixote?","Miguel de Cervantes"
"What is 12 x 12?","144"Sample deck ready to copy to the SD card:
CPR-vCodex is a reading-focused firmware fork for the Xteink X4, built on top of the stable CrossPoint Reader baseline and extended with analytics, reader utilities, branding cleanup, extra UI features, and carefully selected upstream carry-forwards.
The official crosspoint-reader project is treated as the stable reference. vcodex only carries forward upstream work when it is useful on the X4 and safe enough to keep the reader fast and reliable.
There may be some involuntary or incidental X3 compatibility because parts of the upstream codebase still carry X3-aware paths. CPR-vCodex now also includes an experimental X3-only tilt page-turn option for devices with the QMI8658 IMU, but it is hidden when the sensor is not detected and remains off by default. The firmware is still developed and validated on X4, and I do not currently have an X3 device available to test or confirm that compatibility.
This project is not affiliated with Xteink.
- stable upstream-based reader baseline kept fast on large EPUBs
- richer on-device analytics:
Reading Stats,Reading Heatmap,Reading Day,Reading Profile - manual per-book reading-time/date corrections for missed or accidental stats
Achievementsbuilt on top of the same reading data modelSync Dayfor coherent day-based stats on hardware without a trustworthy sleep RTCLyra CarouselHome theme, originally created by zgredex, adapted to this fork by erickosanchezj, limited to 3 books for smoother X4 navigation, with a sliding bottom shortcut row so every configured Home action remains reachable- experimental X3-only
Tilt Page Turn, hidden unless the QMI8658 IMU is detected and disabled by default - downloadable SD-card fonts from CrossPoint plus vCodex families such as
ChareInkandLexend - SD-card firmware update from Settings for local
.binflashing without a browser - configurable long-press side-button behavior:
Off,Chapter skip, orOrientation change - EPUB Highlights for selected text and saved pages, plus a global Highlights app
- context-aware screenshot filenames that include the current book title when available
- KOReader Sync compatibility improvements, including Calibre-Web-Automated
/kosyncsupport - configurable OPDS download filename format:
Author - TitleorTitle - Author - configurable
HomeandAppsshortcuts Flashcardswith offline CSV decks, session summary, recents, stats and settingsText Darkness,Bionic Reading,Reader Refresh Mode, downloadableLexend,X SmallSleeptools with directory selection, preview, cache, sequential and shuffle behaviorDark Mode (Experimental)- Vietnamese UI support and synchronized translation coverage across all shipped languages
CPR-vCodex currently ships with 23 UI languages:
- English
- Spanish
- French
- German
- Czech
- Portuguese
- Russian
- Swedish
- Romanian
- Catalan
- Ukrainian
- Belarusian
- Italian
- Polish
- Finnish
- Danish
- Dutch
- Turkish
- Kazakh
- Hungarian
- Lithuanian
- Slovenian
- Vietnamese
The translation set is maintained from english.yaml as the source of truth. Current shipped UI keys are synchronized across all 23 languages; safe English fallback remains available for future keys that have not been translated yet.
For most users, this is the easiest way to install the firmware:
- Download the latest
*-cpr-vcodex.binrelease file. - Turn on and unlock your Xteink X4.
- Open xteink.dve.al.
- In
OTA fast flash controls, select the firmware file. - Click
Flash firmware from file. - Select the device when the browser asks.
- Wait for the installation to finish.
- Restart the device if needed.
To return to the original CrossPoint Reader later, repeat the same process with the original firmware file.
If you just flashed CPR-vCodex and want the main value quickly:
- Open
Home > Sync Day - Connect to Wi-Fi and sync the date
- Open a book and read normally
- Open
Apps > Reading Stats - Open
Apps > Reading Heatmap
That is enough to start using the core vcodex additions: coherent day-based analytics, better stats visibility, and improved app-level reading tools.
| Feature | What it adds | More info |
|---|---|---|
Reading Stats |
totals, streaks, goal tracking, started books, finished books, and per-book detail | Reading analytics suite |
Manual stats correction |
add or subtract per-book minutes for a selected date without typing on the device | Reading analytics suite |
Reading Heatmap |
monthly calendar of reading intensity | Reading analytics suite |
Reading Day |
one-day drill-down from the heatmap | Reading analytics suite |
Reading Profile |
weekly reading behavior summary | Reading analytics suite |
Achievements |
console-style milestones and optional popups | Achievements |
Flashcards |
offline deck study with Scheduled and Infinite session modes |
Flashcards |
Sync Day |
manual Wi-Fi date sync and fallback-day logic | Sync Day and date model |
Home + Apps shortcuts |
configurable placement, visibility, ordering, and a fallback to Lyra vCodex for removed/unknown themes |
Home and Apps |
SD card fonts |
download, upload, or manually install extra .cpfont families from the SD card |
Settings |
SD firmware update |
select a .bin from the SD card and flash it locally from Settings |
Settings |
Long-press button behavior |
choose Off, Chapter skip, or Orientation change for reader side-button holds |
Settings |
Highlights |
selected EPUB text and saved pages in one backward-compatible app | Highlights |
Sleep tools |
folder selection, preview, cache, sequential and shuffle behavior | Sleep |
Text Darkness |
global Normal / Dark / Extra Dark text rendering control, based on the idea first seen in crosspet |
Settings |
Bionic Reading |
Off / Normal / Subtle EPUB focus-reading modes with stable text weight in BW and anti-aliased rendering |
Settings |
Reader Refresh Mode |
Auto / Fast / Half / Full |
Settings |
Lexend |
downloadable SD-card reader font family | Settings |
Dark Mode (Experimental) |
optional white-on-black UI and reader presentation | Settings |
ReadMe |
on-device quick guide for the main fork features | ReadMe |
If found, please return me |
lost-device contact screen from /if_found.txt on the SD card |
If found, please return me |
Vietnamese UI |
extra UI language with matching font binding | Languages |
The launcher is split into Home and Apps.
Home stays focused on frequently used reading entry points, while Apps collects the richer tools added by the fork.
Notable launcher behavior:
- shortcut placement can be moved between
HomeandApps - shortcut visibility can be toggled
- ordering is configurable
- stats-related shortcuts show useful live metadata
Appspaginates long lists and supports page-jump navigationLyra Carouselis available as an optional cover-focused Home theme and is limited to 3 books for smoother X4 navigation; its bottom shortcut row shows five icons at a time but scrolls laterally with selection so longer Home shortcut lists remain reachable It was originally created by zgredex and adapted to CPR-vCodex by erickosanchezj.
Management lives in:
Settings > Apps > Location Home and AppsSettings > Apps > Visibility Home and AppsSettings > Apps > Order Home shortcutsSettings > Apps > Order Apps shortcuts
This part matters, because several vcodex features depend on day-level data.
The ESP32-C3 in the X4 does not provide a sleep-resilient real-time clock you can trust after every sleep cycle. So the fork uses a practical model:
Sync Dayconnects over Wi-Fi and gets a valid date/time using NTP- that becomes the trusted reference date for stats
- if the live clock later becomes unreliable, the firmware falls back to the last valid saved date
- day-based views stay coherent instead of drifting randomly
In practice:
- syncing once per day before reading is usually enough
- day-based stats depend on having a valid day reference
- timezone and date format are configurable globally
All reading analytics features share the same persistence model and data source.
That means these views stay coherent with each other:
Reading StatsReading HeatmapReading DayReading Profile- per-book stats detail
- started books
- finished books
- total reading time
- daily reading time
- counted sessions
- daily-goal progress
- goal streak and max streak
- per-book progress and last-read state
- a session counts only after reaching the minimum tracked duration
- daily goal is configurable
- day-based analytics depend on a valid synced or recovered day
- books under ignored stats paths are excluded from tracking
| View | Purpose |
|---|---|
Reading Stats |
main analytics hub with goal, streak, totals and started books |
More Details |
wider trends and graphs |
Reading Heatmap |
monthly calendar of reading intensity |
Reading Day |
one-day detail view opened from the heatmap |
Reading Profile |
summary of recent reading behavior |
Per-book stats detail |
cover, progress, sessions, time and last-read info for one book |
Per-book detail also includes a small settings button under the cover. It opens book-specific stats actions:
Adjust reading timeopens the correction screen for missed or accidental reading timeModify start datechanges only the book's displayed start date metadataReset this book's statsasks for confirmation, then removes that book's stats entry, attributed session history, and rebuilds aggregate reading totals
The correction screen can:
- choose
AddorSubtract - choose the exact date with the same numeric picker style used by
Sync Day - choose 15, 30, 45, or 60 minutes
- subtracting is capped so a day can never go below zero
Manual corrections update the same daily totals used by streaks, heatmaps and achievements.
Achievements adds a lightweight progression layer on top of the same reading data used by stats.
It provides:
- a dedicated
Apps > Achievementsscreen - pending vs completed sections
- unlock popups
- reset support
- retroactive sync from existing reading stats
The current catalog rewards, among other things:
- started books
- counted sessions
- finished books
- total reading time
- goal-completion days
- streaks
- bookmark usage
- long sessions
ReadMe is an on-device quick guide for the main fork features.
It includes compact help pages for:
Sync DayReading StatsBookmarksFlashcardsSleepCustomize Home and AppsAchievementsIf found, please return me
This gives device-side help without needing to reopen GitHub every time.
This app is a simple lost-device return screen.
How it works:
- open
Apps > If found, please return me - the screen always shows a fixed intro message
- if
/if_found.txtexists on the SD root, its content is shown below - common filename/encoding variants are tolerated, including case differences,
if_found.txt.txt, UTF-8 BOM, and UTF-16 text files - if the file does not exist, the app shows a fallback message explaining how to create it
Highlights are implemented for EPUB as one feature with two entry types:
- text highlights for a selected phrase
- page marks, preserving the behavior and data of the previous Bookmarks feature
Supported flow:
- open the reader menu and choose
Highlight text; select the first and last word, then save - long-press
Selectinside EPUB reading to toggle a page mark - use
Save page markwhen the current page should be kept without toggling it - open
View highlightsor the globalApps > Highlightsscreen to browse both types together - reopen a book at the saved page and delete individual entries or all highlights for one book
Existing bookmarks.bin files remain readable. They are upgraded in place only when
the user next changes the book's Highlights, and all old bookmarks become page-mark
entries rather than being discarded. Format v5 adds a visible Unicode-codepoint anchor
to new page marks and text highlights, so reopening them remains tied to the same content
after changing font size, margins, line spacing, or orientation.
Highlights also recognize words split by a layout-inserted hyphen and adjacent ellipsis/NBSP fragments after reflow. A hyphen authored in the EPUB remains part of the text and is never silently discarded by matching.
The text-selection and on-page highlighting behavior is adapted from
CrossInk by
Julia Nguyen (uxjulia), beginning with CrossInk
commit b4d0ee1
and incorporating relevant later robustness fixes through
ffda6de.
Flashcards is an offline study app built around CSV decks on the SD card.
Main sections:
OpenRecentsStatisticsSettings
Deck flow:
- open a CSV deck from the SD card
- study in landscape using
Flip,Next,SuccessandFail - leave the deck through the page buttons when you want to finish
- get a session summary when you exit
Study modes:
Due: finite review-oriented session, using due cards first and unseen cards secondScheduled: finite shuffled session from the whole deckInfinite: endless practice, ignoresSession sizeSequential: whole deck in CSV order, ignoresSession size
Statistics:
- each deck keeps its own seen / unseen / due / mastered metrics
Statisticslists known decks- holding
Selecton a deck insideStatisticslets you reset that deck's flashcard stats after confirmation
The Sleep app makes custom sleep images easier to manage.
It supports:
- directory discovery
- preview
- sequential vs shuffle order
- persistent selected directory
- case-insensitive default folders such as
/Sleep,/sleep, and/.Sleep - cached sleep framebuffers
- reduced repetition through recent-wallpaper tracking
Reading Dashboardsleep mode with daily goal, streak, reading totals, and achievement progressCover + StatsandCustom + Statssleep modes with compact reading overlays on either the current cover or configured custom images
The most important fork-specific options are concentrated in Settings > Apps, while reader and display behavior stay under the normal settings categories.
Useful reader/display additions include:
| Area | Options |
|---|---|
| Reader | Text Anti-Aliasing, Text Darkness, Bionic Reading, Reader Refresh Mode, Reader Font Family, Reader Font Size, Manage Fonts |
| Display | UI Theme, sleep-screen controls, Dark Mode (Experimental), Sunlight Fading Fix |
| Controls | Side Button Layout, Long-press button behavior, Short Power Button Click, Tilt Page Turn |
| Status bar | EPUB/status-bar fields, battery visibility, XTC Status Bar |
| System | Hide File Extension, SD Card Firmware Update, OTA update check, cache clearing, language, OPDS servers |
| Date | Display Day, Date Format, Time Zone, Sync Day reminder behavior |
| Reading stats | Daily Goal, Show after reading, Reset Reading Stats, Export Reading Stats, Import Reading Stats |
| Achievements | Enable achievements, Achievement popups, Reset achievements, Sync with prev. stats |
| Navigation | Location Home and Apps, Visibility Home and Apps, Order Home shortcuts, Order Apps shortcuts |
Text Darkness is a feature idea seen in the crosspet fork and adapted here for vcodex.
Font notes:
BookerlyandNoto Sanshave full regular/bold/italic coverage in the compiled sizesLexendis available as a downloadable SD-card reader familyLexenditalic and bold-italic still use safe fallbacks rather than separate real italic assetsManage Fontsdownloads common SD-card font families from CrossPoint and CPR-vCodex additions, currentlyChareInkandLexend
Anything tied to day-level analytics depends on having a valid day reference.
That includes:
- daily goal
- goal streak
- max goal streak
- heatmap
today7D30D- last read date
Recommended rule:
- do
Sync Dayonce before reading each day
CPR-vCodex keeps storage compatibility as a first priority.
It does not use a database. User state is persisted mainly under /.crosspoint/.
Important artifacts include:
/.crosspoint/state.json/.crosspoint/reading_stats.json/.crosspoint/achievements.json/.crosspoint/recent.json- per-book
bookmarks.bin, now a versioned Highlights store that retains legacy page bookmarks /exports/stats_exportedfor manual Reading Stats export/import/exports/stats_backup_YYYY-MM-DDfor automatic dated Reading Stats backups (every 7 days by default)
Update to 1.6.0.37-cpr-vcodex before resetting or deleting any data. In most cases the existing /.crosspoint/reading_stats.json will load automatically after the update because the affected releases rejected the file without overwriting it.
If the displayed totals are still incomplete or incorrect, open Settings > Apps > Reading Stats > Import Reading Stats and select the newest suitable dated backup under /exports/stats_backup_YYYY-MM-DD. Those weekly backups appear directly in the import list and do not need to be renamed. If the only copy is on a computer, place it on the SD card as exactly /exports/stats_exported (without a .json extension), then import it. Try older dated backups newest-first if necessary, and preserve a copy of the SD card before cleaning or resetting statistics.
This is one of the main reasons the fork was rebuilt on a cleaner upstream-derived base instead of continuing to patch the older fork in place.
Each packaged dev build now keeps the base firmware line and the local flash identity easy to distinguish.
Practical values to look at:
- base firmware line:
CrossPoint Reader 1.6.0 - current release build style:
1.6.0.37-cpr-vcodex - packaged artifact style:
artifacts/<version>-cpr-vcodex.bin
The incremental .bNNNN suffix exists specifically to help distinguish newer flashes from older ones on real hardware.
- User Guide
- Scope
- i18n notes
- Contributing docs
- Touch and UI development - how to build screens on the FreeInkUI activity bases (UiListActivity and friends) so they work with both buttons and the X4 Pro touchscreen
- Web server usage and endpoints
- SD card fonts and dictionaries
| Document | Purpose |
|---|---|
| STEROIDS-ADDICTIONS.md | Main index of all Steroids features |
| STEROIDS-ADDICTIONS-LIBRARY.md | Library V3 complete spec |
| STEROIDS-ADDICTIONS-READING-STATS.md | Streaming stats + journal + import |
| STEROIDS-ADDICTIONS-FAST-RESTART.md | Declarative fast restart |
| STEROIDS-ADDICTIONS-HOME-THEMES.md | Lyra Marcoand75 theme |
| STEROIDS-ADDICTIONS-BRANDING.md | Logo, web UI, OTA URLs |
| STEROIDS-ADDICTIONS-LUA.md | Lua plugin system |
| STEROIDS-ADDICTIONS-WIKIPEDIA.md | Wikipedia offline |
| STEROIDS-ADDICTIONS-SLEEP.md | Sleep screen + power button |
| STEROIDS-ADDICTIONS-SCREENSAVER.md | Screensaver |
| STEROIDS-ADDICTIONS-QUICK-CARDS.md | Flashcard SM-2 |
| STEROIDS-ADDICTIONS-COVER-GEN.md | Cover generation fixes |
| STEROIDS-ADDICTIONS-SETTINGS.md | Settings + web API |
| STEROIDS-ADDICTIONS-I18N.md | 24 languages |
| STEROIDS-ADDICTIONS-SHORTCUTS.md | CTAD shortcut registry |
| STEROIDS-ALIGN-TO-UPSTREAM.md | Upstream merge strategy |
- pioarduino PlatformIO Core (
pio) orVS Code + pioarduino IDE - Python 3.8+
clang-format21 (for contributor formatting checks)- USB-C cable supporting data transfer
- Xteink X4 or X3 (ESP32-C3)
- Xteink X3 compatibility has been reported by users, but this maintainer does not have X3 hardware for direct validation
Possible note about X3:
- the codebase may still retain some upstream X3-aware behavior
- the X3-only
Tilt Page Turnsetting is experimental, off by default, and hidden unless the QMI8658 IMU is detected CPR-vCodexis not validated on X3 hardware- no X3 device is currently available for testing
Use the project build wrapper:
.\bin\build-vcodex.ps1The wrapper forces UTF-8 Python/console output for PlatformIO on Windows and uses one build job by default for more repeatable local diagnostics. You can still pass another environment or job count explicitly:
.\bin\build-vcodex.ps1 -Environment gh_release_rc -Jobs 2Warning
X4 Pro release binaries are not published. The source retains an internal ESP32-S3 environment for maintainers investigating the hardware, but it is not a supported installation path. Do not give local X4 Pro builds to users, especially owners of CN/USB-locked units, until a tested recovery procedure exists.
To verify the gh_release environment locally without advancing the release
counter or rewriting this README:
$env:VCODEX_RELEASE_DRY_RUN = "1"
.\bin\build-vcodex.ps1 -Environment gh_release
Remove-Item Env:\VCODEX_RELEASE_DRY_RUNThis generates a packaged firmware artifact under:
artifacts/<version>-cpr-vcodex.bin
Versioning rules:
- release builds:
1.6.0.<release>-cpr-vcodex.bin - dev builds:
1.6.0.<release>.dev<build>-<sha>-cpr-vcodex.bin - internal maintainer-only X4 Pro builds carry
-x4pro; these artifacts must not be distributed while the safety withdrawal remains active
Release publishing:
- before tagging, run:
python scripts/pre_release_check.py --tag 1.6.0.37-cpr-vcodex- push a stable tag named like
1.6.0.37-cpr-vcodex pre_release_check.pydry-runsgh_release, checks it against the 6,553,600 byte X4 OTA slot, validates the artifact pair, and rejects any X4 Pro entry or stale X4 Pro browser binary- the release workflow builds
gh_releaseand attaches only<tag>.bin, its build metadata, and its firmware-budget reports (four assets) - tagged CI release builds derive the firmware release number from the tag, not from a local counter file
- the auto-flash sync workflow mirrors the published C3 release asset into
docs/firmware/firmware.bin, removes any stalefirmware-x4pro.bin, and writes onlydevices.x4anddevices.x3to the manifest
Huge credit goes to:
- the CrossPoint Reader project for the upstream base
- the Xteink X4 community around the firmware ecosystem
- zgredex for the original
Lyra CarouselHome theme - erickosanchezj for adapting
Lyra Carouselto CPR-vCodex - Julia Nguyen (
uxjulia) and her CrossInk fork for the original clipping/highlighting feature adapted into CPR-vCodex Highlights - Which-Estimate4566 for the logo artwork used in the docs
CPR-vCodex is not affiliated with Xteink or any manufacturer of the X4 hardware.
