SABRAMAN

SABRAMAN DANYA YUDIN КАРТОН SABRAMAN DANYA YUDIN КАРТОН SABRAMAN DANYA YUDIN КАРТОН SABRAMAN DANYA YUDIN КАРТОН SABRAMAN DANYA YUDIN КАРТОН SABRAMAN DANYA YUDIN КАРТОН
Embedded EPUB Engine
C++ · SDL2 · PSPSDK

PSP Book Reader

Native C++ EPUB reader for Sony PSP (480x272 screen, 32MB RAM) focused on stable long-form reading on 2004 handheld hardware.

Project Context

PSP was designed as a game console, not an e-reader. It has no native EPUB workflow, a low-resolution 480x272 display, and strict memory limits on PSP-1000 (32MB RAM).

The target was practical daily reading: fast library scan, chapter navigation, progress restore, readable typography, and battery-aware behavior without UI stalls.

The project scope covers the full stack: EPUB ZIP/XML parsing, XHTML text extraction, font rendering, input handling, settings persistence, and PSP power integration.

EPUB Processing Pipeline

Container parsing, chapter loading, and rendering are isolated so each stage stays predictable on legacy hardware.

01

ZIP container extraction (miniz)

02

container.xml -> OPF metadata/spine

03

NCX navigation mapping + chapter titles

04

On-demand chapter load + XHTML tokenization

05

CJK-aware line breaking + incremental layout

06

Cached glyph rendering + progress persistence

Runtime Power Modes

Performance

333 / 166 MHz

Library scanning and intensive tasks

Balanced

222 / 111 MHz

Primary UI and navigation

Saving

66 / 33 MHz

Idle > 2s and passive reading

Mode

Frequency

Usage

Architecture

The app is built as a modular, event-driven system with a core state machine (`library`, `reader`, `settings`) in the main loop.

EPUB parsing uses miniz + pugixml: `container.xml` -> OPF metadata/spine -> NCX navigation mapping, with chapter files loaded on demand.

Rendering and text layout are separated from parsing: extracted tokens flow into an incremental layout pipeline and then into cached SDL texture rendering.

Implementation Notes

The stack uses SDL2, SDL2_ttf/FreeType, SDL2_image, miniz, pugixml, and PSP kernel APIs through PSPSDK Makefile builds.

Layout is incremental and frame-budgeted: default 500 words/frame, burst to 1000 when the user is waiting, which keeps navigation responsive during pagination.

Text rendering uses dual-tier LRU caches (120 texture entries + 1000 metrics entries) with FNV-1a keys to avoid repeated glyph and width work.

Dynamic power control switches between 333/166, 222/111, and 66/33 MHz tiers with idle detection (>2s) and frame throttling (1ms vs 32ms delay).

Memory guards reject oversized assets: cover extraction is capped (2MB), and oversize textures are resampled to PSP-friendly limits (including GE 512x512 constraints).

Key Runtime Metrics

Incremental layout budget

500 words/frame, burst to 1000

Text cache

120 textures + 1000 metrics

Progress restore anchor

Word-index anchors in config.bin

Memory guard

2MB cover cap + PSP-safe textures

Core Reader Capabilities

Reading progress is anchored by word index and persisted in `config.bin`, so reopening a book restores chapter and position without full re-navigation.

TATE vertical mode rotates rendering and remaps controls, making one-handed and vertical reading usable on the PSP form factor.

Typography supports Latin/Cyrillic/CJK through font mode switching (Inter + Droid Sans Fallback), with page layout that remains stable under constrained memory.

The library layer handles metadata, cover handling, and cached scanning so large collections remain navigable without repeated heavy parsing.

Optimization Stack

  • Incremental pagination instead of blocking full-chapter layout
  • Stable LRU eviction without memory spikes
  • CPU/ME frequency profiles tied to user activity
  • CJK line-break heuristic without a heavy script engine

Outcome

The project turns PSP into a reliable EPUB reader with practical library browsing, chapter navigation, and session continuity on real hardware.

The main engineering result is consistency under constraints: predictable frame behavior, controlled memory usage, and readable typography across mixed scripts.

It is not trying to copy tablet readers feature-by-feature; it is a hardware-conscious implementation that stays usable over long reading sessions.

Tradeoffs

Compared to desktop/mobile readers, feature scope is intentionally narrower: performance and stability take priority over full CSS-like layout parity.

Implementation complexity shifts into low-level paths: cache invalidation, memory guards, and power-mode transitions must be explicit and testable.

PSP-specific behavior (GPU limits, controller semantics, clock APIs) requires hardware-aware testing, not only desktop emulation.

Technical Deep Dives

Architecture notes generated from repository code and implementation walkthroughs.

FAQ

What was the hardest engineering challenge?

Balancing frame responsiveness, layout throughput, and battery behavior at the same time. The system had to stay interactive while parsing and paginating long chapters.

How does CJK line breaking work on PSP?

A lightweight UTF-8 heuristic treats typical 3-byte CJK sequences as standalone tokens, so the standard wrapping pipeline can break lines correctly without a heavy script engine.

How are memory spikes prevented on 32MB RAM?

By strict size-aware loading and cache discipline: ZIP file sizes are checked before allocation, oversized covers are blocked/resampled, and LRU eviction keeps texture/metrics memory bounded.

External links