# CrossPoint Reader (Mod) A modified fork of [CrossPoint Reader](https://github.com/crosspoint-reader/crosspoint-reader) for the **Xteink X4** e-paper display reader. Built using **PlatformIO** and targeting the **ESP32-C3** microcontroller. This mod is maintained on the `mod/master` branch and tracks upstream `master`. It ports upstream PRs ahead of merge and adds features not yet available in the official project, including bookmarks, dictionary lookup, a clock, book management with archiving, an overhauled reader menu, and various rendering and performance improvements. > **Upstream:** [crosspoint-reader/crosspoint-reader](https://github.com/crosspoint-reader/crosspoint-reader) ![](./docs/images/cover.jpg) ## Motivation E-paper devices are fantastic for reading, but most commercially available readers are closed systems with limited customisation. The **Xteink X4** is an affordable, e-paper device, however the official firmware remains closed. CrossPoint exists partly as a fun side-project and partly to open up the ecosystem and truly unlock the device's potential. CrossPoint Reader aims to: * Provide a **fully open-source alternative** to the official firmware. * Offer a **document reader** capable of handling EPUB content on constrained hardware. * Support **customisable font, layout, and display** options. * Run purely on the **Xteink X4 hardware**. This mod exists to iterate faster on features and fixes while upstream reviews and merges PRs at its own pace. It is **not affiliated with Xteink** or the upstream CrossPoint project; it's a personal fork built on top of their work. ## History This mod was forked at [#46c2109](https://github.com/crosspoint-reader/crosspoint-reader/commit/46c2109f1fe5cb41ef1a84a15eeb3db64cdca082). A major sync took place at v1.1.0-rc. ## Features & Usage This is not all-inclusive, but in general: - [x] EPUB parsing and rendering (EPUB 2 and EPUB 3) - [x] Image support within EPUB (JPEG and PNG) - [x] Table rendering within EPUB - [x] Saved reading position - [x] Bookmarks (add, remove, navigate with snippet preview) - [x] Dictionary lookup (offline, StarDict format) - [x] File explorer with file picker - [x] Basic EPUB picker from root directory - [x] Support nested folders - [x] File extensions displayed - [x] Expandable selected row for long filenames - [ ] EPUB picker with cover art - [x] Book management (archive, unarchive, delete, reindex) - [x] Clock display (12h/24h, NTP sync, timezone support) - [x] Custom sleep screen - [x] Cover sleep screen - [x] Letterbox fill modes (Solid, Dithered, None) with per-book override - [x] Placeholder covers for books without embedded cover images - [x] Wifi book upload - [x] Wifi OTA updates - [x] Configurable font, layout, and display options - [ ] User provided fonts - [ ] Full UTF support - [x] Screen rotation (Portrait, Landscape CW, Inverted, Landscape CCW) - [x] End-of-book interactive menu - [x] Silent background chapter pre-indexing Multi-language support: Read EPUBs in various languages, including English, Spanish, French, German, Italian, Portuguese, Russian, Ukrainian, Polish, Swedish, Norwegian, [and more](./USER_GUIDE.md#supported-languages). See [the user guide](./USER_GUIDE.md) for instructions on operating CrossPoint. For more details about the scope of the project, see the [SCOPE.md](SCOPE.md) document. ## What This Mod Adds This section describes features and improvements in the mod that are not present in upstream CrossPoint Reader. ### Reading Enhancements * **Bookmarks** — Save and remove bookmarks per book. Each bookmark stores a snippet (first sentence) for quick identification. A ribbon indicator marks bookmarked pages. Navigate bookmarks via the reader menu. * **Dictionary lookup** — Offline word lookup using StarDict-format dictionaries stored in `/.dictionary/` on the SD card. Supports stemming, fuzzy matching, edit-distance suggestions, and lookup history. The dictionary index is cached to a binary file for fast subsequent access. * **Table rendering** — EPUB tables render with column alignment, colspan support, HTML/CSS width hints, cell padding, borders, and `
` line breaks within cells. Full-width spanning cells are center-aligned. * **End-of-book menu** — An interactive menu at the end of a book (Archive, Delete, Back to Beginning, Close) replaces the static end-of-book text. * **Long-press Confirm** — While reading, long-pressing Confirm opens the Table of Contents directly, bypassing the reader menu. ### Home Screen & Navigation * **Clock** — Displays in all screen headers. Configurable format (off, 12h AM/PM, 24h) and size (small, medium, large). Supports NTP time sync over WiFi, timezone presets (UTC, US time zones), and custom UTC offset. * **Adaptive home screen** — Book card sizing adjusts based on cover aspect ratio. The home screen integrates with recent books and book management. * **File browser improvements** — File extensions are shown alongside filenames. When a selected filename overflows the row width, the row expands to two lines with smart text wrapping (breaks at dashes/separators, then word boundaries, then character-level). * **Long-press shortcuts** — Long-press on a book in the home screen or recents opens the book management menu. Long-press on "Browse Files" opens the archive browser (`/.archive/`). ### Book Management * **Archive** — Move books to `/.archive/` on the SD card, preserving directory structure. Unarchive restores them to their original location. * **Manage Book menu** — A popup menu accessible from the home screen, file browser, recents, reader menu, and end-of-book menu. Actions include archive/unarchive, delete book, delete cache, reindex, and full reindex. * **Recent books** — A dedicated recent books list with book management integration. ### Reader Menu * **Long-press actions** — Long-press "Lookup Word" to open the Looked Up Words history. Long-press "Toggle Orientation" to open a sub-menu for selecting any of the four orientations (Portrait, Landscape CW, Inverted, Landscape CCW). * **Letterbox fill** — Short-press cycles through letterbox fill modes (Default, Dithered, Solid, None). Per-book overrides are stored in `BookSettings`. * **Landscape CCW** — A fourth orientation option. All text rendering, button hints, and dictionary layout support counter-clockwise landscape. ### Display & Rendering * **Silent pre-indexing** — The next chapter is pre-indexed in the background when approaching a chapter boundary. Configurable display mode: popup, status bar text, or status bar icon. * **Placeholder covers** — Books without an embedded cover image get a generated placeholder (title, author, icon layout) for the home screen and sleep screen. * **Sleep screen letterbox fill** — Multiple fill modes for the letterbox area around cover images on the sleep screen, with per-book override support. ### Performance Several upstream PRs have been ported ahead of their merge into upstream `master`: * **Byte-level framebuffer writes** — 232-470x speedup for `fillRect`, `fillRectDither`, and axis-aligned `drawLine` operations. Upstream [PR #1055](https://github.com/crosspoint-reader/crosspoint-reader/pull/1055). * **Word-width cache and hyphenation early exit** — 5-9% layout time reduction via a 128-entry direct-mapped cache and monotonic early exit in the hyphenation loop. Upstream [PR #1027](https://github.com/crosspoint-reader/crosspoint-reader/pull/1027). * **`std::list` to `std::vector` in text layout** — 11% faster chapter parse time and ~50KB heap savings. Upstream [PR #1038](https://github.com/crosspoint-reader/crosspoint-reader/pull/1038). * **Combining mark rendering** — Proper rendering of decomposed Unicode characters with NFC-like precomposition for hyphenation pattern matching. Upstream [PR #1037](https://github.com/crosspoint-reader/crosspoint-reader/pull/1037). * **URL hyphenation** — Long URLs can now be line-wrapped at path separators without crashing. Upstream [PR #1068](https://github.com/crosspoint-reader/crosspoint-reader/pull/1068). For detailed porting notes and differences from upstream, see [mod/prs/MERGED.md](mod/prs/MERGED.md). Note that this document was created well after many features were added manually so it is not all-inclusive. Sorry! ## Upstream Compatibility This mod tracks upstream `master` and manually ports relevant PRs. Some upstream features are not present in the mod, and the mod's build configuration differs slightly. **Features on upstream `master` not yet in the mod:** * Catalan language support * Improved Spanish translations **Build differences:** * The `[env:mod]` build environment omits the OpenDyslexic font and some hyphenation patterns (German, Spanish, French, Italian, Russian) to save flash space. These can be re-enabled by using `[env:default]` or removing the corresponding `-DOMIT_*` flags. * The mod version string is `-mod+` (e.g., `1.1.2-mod+abc1234`). See [mod/prs/MERGED.md](mod/prs/MERGED.md) for the full list of upstream PRs ported into this mod, including what was changed or enhanced during the port. ## Installing This mod is built from source. There is no web flasher for the mod firmware. Connect your Xteink X4 to your computer via USB-C, wake/unlock the device, and run: ```sh pio run -e mod --target upload ``` You can also use `pio run -e default --target upload` for a build without the mod's flash-saving omissions (see [Upstream Compatibility](#upstream-compatibility)). To revert to upstream CrossPoint or the official Xteink firmware, flash via https://xteink.dve.al/ or swap back to the other partition using the "Swap boot partition" button at https://xteink.dve.al/debug. ## Development ### Prerequisites * **PlatformIO Core** (`pio`) or **VS Code + PlatformIO IDE** * Python 3.8+ * USB-C cable for flashing the ESP32-C3 * Xteink X4 ### Checking out the code CrossPoint uses PlatformIO for building and flashing the firmware. To get started, clone this repository and check out the mod branch: ```sh git clone --recursive -b mod/master https://github.com/crosspoint-reader/crosspoint-reader # Or, if you've already cloned without --recursive: git submodule update --init --recursive ``` ### Build environments | Environment | Description | | ----------- | ----------- | | `mod` | **Recommended.** Includes serial logging, version tagging (`-mod+`), and omits some fonts/hyphenation patterns to save flash. | | `default` | Standard upstream-equivalent build with all fonts and hyphenation patterns included. | ### Flashing your device Connect your Xteink X4 to your computer via USB-C and run: ```sh pio run -e mod --target upload ``` ### Debugging After flashing the new features, it’s recommended to capture detailed logs from the serial port. First, make sure all required Python packages are installed: ```python python3 -m pip install pyserial colorama matplotlib ``` after that run the script: ```sh # For Linux # This was tested on Debian and should work on most Linux systems. python3 scripts/debugging_monitor.py # For macOS python3 scripts/debugging_monitor.py /dev/cu.usbmodem2101 ``` Minor adjustments may be required for Windows. ## Internals CrossPoint Reader is pretty aggressive about caching data down to the SD card to minimise RAM usage. The ESP32-C3 only has ~380KB of usable RAM, so we have to be careful. A lot of the decisions made in the design of the firmware were based on this constraint. ### Data caching The first time chapters of a book are loaded, they are cached to the SD card. Subsequent loads are served from the cache. This cache directory exists at `.crosspoint` on the SD card. The structure is as follows: ``` .crosspoint/ ├── epub_12471232/ # Each EPUB is cached to a subdirectory named `epub_` │ ├── progress.bin # Stores reading progress (chapter, page, etc.) │ ├── cover.bmp # Book cover image (once generated) │ ├── book.bin # Book metadata (title, author, spine, table of contents, etc.) │ └── sections/ # All chapter data is stored in the sections subdirectory │ ├── 0.bin # Chapter data (screen count, all text layout info, etc.) │ ├── 1.bin # files are named by their index in the spine │ └── ... │ └── epub_189013891/ ``` Deleting the `.crosspoint` directory will clear the entire cache. Due the way it's currently implemented, the cache is not automatically cleared when a book is deleted and moving a book file will use a new cache directory, resetting the reading progress. For more details on the internal file structures, see the [file formats document](./docs/file-formats.md). ## Contributing This is a personal mod fork. If you'd like to contribute to the upstream CrossPoint Reader project, head to the [upstream repository](https://github.com/crosspoint-reader/crosspoint-reader) and check out the [ideas discussion board](https://github.com/crosspoint-reader/crosspoint-reader/discussions/categories/ideas). For more details on upstream governance and community principles, see [GOVERNANCE.md](GOVERNANCE.md). --- CrossPoint Reader is **not affiliated with Xteink or any manufacturer of the X4 hardware**. This mod is not **not affilitated with CrossPoint Reader**. Huge shoutout to [**diy-esp32-epub-reader** by atomic14](https://github.com/atomic14/diy-esp32-epub-reader), which was a project the original CrossPoint author took a lot of inspiration from.