SABRAMAN

SABRAMAN DANYA YUDIN КАРТОН SABRAMAN DANYA YUDIN КАРТОН SABRAMAN DANYA YUDIN КАРТОН SABRAMAN DANYA YUDIN КАРТОН SABRAMAN DANYA YUDIN КАРТОН SABRAMAN DANYA YUDIN КАРТОН
Embedded EPUB-движок
C++ · SDL2 · PSPSDK

PSP Book Reader

Нативный C++ EPUB-ридер для Sony PSP (экран 480x272, 32MB RAM), рассчитанный на стабильное чтение длинных текстов на железе 2004 года.

Контекст проекта

PSP проектировалась как игровая консоль, а не как ридер. У нее нет нативного EPUB-сценария, экран 480x272 и жесткие ограничения памяти на PSP-1000 (32MB RAM).

Целью было практичное ежедневное чтение: быстрый скан библиотеки, навигация по главам, восстановление прогресса, читабельная типографика и бережное энергопотребление без фризов UI.

Проект охватывает полный стек: парсинг EPUB ZIP/XML, извлечение текста из XHTML, рендеринг шрифтов, обработку ввода, сохранение настроек и интеграцию с энергоменеджментом PSP.

EPUB-пайплайн обработки

Парсинг контейнера, загрузка глав и рендер отделены друг от друга, чтобы каждый этап оставался предсказуемым на старом железе.

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

Режимы энергопотребления

Performance

333 / 166 MHz

Скан библиотеки и тяжелые операции

Balanced

222 / 111 MHz

Основной UI и навигация

Saving

66 / 33 MHz

Idle > 2с и чтение без активности

Режим

Частоты

Сценарий

Архитектура

Приложение собрано как модульная event-driven система с центральной state machine (`library`, `reader`, `settings`) в основном цикле.

Парсинг EPUB построен на miniz + pugixml: `container.xml` -> OPF metadata/spine -> NCX-навигация, а файлы глав загружаются по требованию.

Рендер и layout текста отделены от парсинга: извлеченные токены проходят через инкрементальный layout-пайплайн и далее в кэшируемый рендер SDL-текстур.

Заметки по реализации

Стек построен на SDL2, SDL2_ttf/FreeType, SDL2_image, miniz, pugixml и PSP kernel API через сборку PSPSDK Makefile.

Layout инкрементальный и ограничен бюджетом кадра: базово 500 слов/кадр, ускорение до 1000 при ожидании пользователя, что сохраняет отзывчивость навигации во время пагинации.

Рендер текста использует двухуровневый LRU-кэш (120 текстур + 1000 метрик) с FNV-1a ключами, чтобы не пересчитывать глифы и ширины повторно.

Динамическое энергопотребление переключает режимы 333/166, 222/111 и 66/33 MHz по активности (>2с idle) и троттлингу кадров (1ms против 32ms задержки).

Memory guards отсекают слишком тяжелые ресурсы: извлечение обложек ограничено (2MB), а крупные текстуры ресемплируются под лимиты PSP (включая ограничения GE 512x512).

Ключевые runtime-метрики

Инкрементальный budget layout

500 слов/кадр, буст до 1000

Текстовый кэш

120 текстур + 1000 метрик

Якорь восстановления прогресса

Якоря по word index в config.bin

Memory guard

Лимит 2MB для обложек + PSP-safe текстуры

Ключевые возможности ридера

Прогресс чтения привязан к индексу слова и сохраняется в `config.bin`, поэтому книга открывается с нужной главы и позиции без повторной навигации.

Вертикальный TATE-режим поворачивает рендер и ремапит управление, делая вертикальное и одноручное чтение на PSP практически удобным.

Типографика поддерживает Latin/Cyrillic/CJK через переключение font mode (Inter + Droid Sans Fallback), при этом layout страниц остается стабильным при ограниченной памяти.

Библиотечный слой отвечает за метаданные, обложки и кэш сканирования, чтобы большие коллекции оставались навигируемыми без повторного тяжелого парсинга.

Стек оптимизаций

  • Инкрементальная пагинация вместо блокирующего full-layout
  • Стабильная эвикция LRU без memory spikes
  • Частотные профили CPU/ME под активность пользователя
  • CJK line-break эвристика без тяжелого script engine

Результат

Проект превращает PSP в надежный EPUB-ридер с практичной библиотекой, навигацией по главам и сохранением сессии на реальном устройстве.

Главный инженерный результат — стабильность в ограничениях: предсказуемое поведение кадров, контролируемая память и читаемая типографика для смешанных письменностей.

Проект не копирует планшетные ридеры по списку функций; это hardware-conscious реализация, которая остается удобной на длительных сессиях чтения.

Компромиссы

По сравнению с desktop/mobile ридерами функциональность намеренно уже: приоритет у производительности и стабильности, а не у полного паритета с CSS-подобным layout.

Сложность реализации уходит в низкоуровневые механики: инвалидация кэша, memory guards и переключения power mode должны быть явными и проверяемыми.

PSP-специфика (лимиты GPU, семантика контроллера, clock API) требует hardware-aware тестирования, а не только эмуляции на десктопе.

Технические deep dive

Архитектурные заметки, собранные по коду репозитория и подробным walkthrough-материалам.

FAQ

Что было самым сложным инженерным вызовом?

Сбалансировать отзывчивость кадров, скорость layout и энергопотребление одновременно. Система должна оставаться интерактивной во время парсинга и пагинации длинных глав.

Как реализован перенос CJK-текста на PSP?

Легкая UTF-8 эвристика рассматривает типичные 3-байтные CJK-последовательности как отдельные токены, поэтому стандартный пайплайн переноса строк работает корректно без тяжелого script-engine.

Как предотвращаются memory spikes при 32MB RAM?

Через жесткую size-aware загрузку и кэш-дисциплину: размеры ZIP-файлов проверяются до аллокации, слишком крупные обложки блокируются/ресемплируются, а LRU-эвикция удерживает память текстур/метрик в границах.

Внешние ссылки