릴리즈 노트

CrossPoint Reader 한국어 펌웨어 버전별 변경사항

현재 버전v1.2.0-ko.15

v1.2.0-ko.8

1.2.0-ko.82026년 4월 21일
GitHub

요약

OTA 업데이트 관련 문제들을 수정했습니다.

Upstream 변경 사항

  • 없음 (upstream 1.2.0 기준 유지)

한국어 버전 변경 사항

  • ko.N 접미사 감지: OtaUpdateActivity 가 업스트림 isUpdateNewer() (semver만 비교) 대신 isUpdateNewerKO() 를 호출하도록 수정. 1.2.0-ko.N1.2.0-ko.M (M>N) 범프가 이제 정상적으로 업데이트로 감지됩니다.
  • 첫 시도 실패: checkForUpdate()timeout_ms=15000 추가 + WiFi 연결 직후 TLS 지연을 대비해 1회 자동 재시도.
  • chunked 응답 처리: GitHub API 가 간헐적으로 Transfer-Encoding: chunked 로 응답할 때 버퍼가 할당되지 않던 문제. 초기 16KB seed 후 realloc 로 확장.
  • 진행률 0% 고정: installUpdate()loop() 를 block 하는 동안 render task 가 깨어나지 않아 UI 가 0% 로 머무르던 문제. ProgressCallback 을 추가해 OTA perform 루프에서 직접 requestUpdate() 호출.
  • 2초 간격 heartbeat 로그([OTA] perform: read=...) 추가 — 느린 TLS/redirect 구간에서도 시리얼로 진행 여부 확인 가능.
  • "업데이트 없음" 문구를 "현재 최신 버전입니다" 로 변경.

v1.2.0-ko.7

1.2.0-ko.72026년 4월 20일
GitHub

요약

TXT 파일 읽기 경험을 두 가지 축에서 크게 개선합니다:
  1. 파일 크기 무관 즉시 열기 — 이전에는 첫 진입 시 전체 파일을 스캔해 모든 페이지 경계를 계산하느라 1MB 에서 수 초, 40MB 에서는 분 단위로 걸렸습니다. 타 리더기(Murphy 3.7 등)가 같은 파일을 바로 여는 것과 같은 방식인 바이트 오프셋 기반 네비게이션으로 전환했습니다.
  2. 양쪽 정렬 동작 — 기존에는 TXT 에서 "양쪽 정렬"을 선택해도 조용히 왼쪽 정렬로 렌더링되던 문제를 수정해 실제로 양쪽 끝을 맞춥니다.

한국어 버전 변경 사항

성능

  • TXT 파일 인덱싱 제거 — 파일 크기 무관하게 즉시 열림 (TxtReaderActivity)
    • 이전 방식: 첫 진입 시 전체 파일을 스캔해 모든 페이지 시작 오프셋을 pageOffsets 벡터에 저장. O(N) 시간·메모리. "Indexing..." 팝업이 수 초~분 단위 표시됨.
    • 새 방식: 현재 페이지의 바이트 오프셋 currentOffset 만 보관. 렌더링 부산물로 다음 페이지 시작 currentEndOffset 을 얻음. 페이지 인덱스를 만들지 않으므로 O(1).
    • 뒤로 가기: 최근 256 페이지의 시작 오프셋을 스택에 보관. 그 이상은 샘플링된 페이지당 평균 바이트로 역산해 근사치 계산 (실제 이전 페이지와 한 페이지 이내 차이).
    • 총 페이지 수 표시 (N/M): 첫 렌더된 페이지의 바이트 수를 기반으로 추정. 진행도 %currentOffset / fileSize 로 정확.
  • progress.bin 캐시 단순화: 페이지 오프셋 배열(파일당 수십 KB) 대신 현재 오프셋 1 개만 저장. 40MB TXT 의 캐시가 수십 바이트로 축소.

수정

  • TXT 양쪽 정렬 실제 동작loadPageAtOffset 이 각 디스플레이 라인을 문단 끝 (소스의 \n 직전) vs 소프트 래핑된 중간 줄로 구분해 출력. renderPage 가 소프트 래핑 줄에서는 (contentWidth - textWidth) 를 UTF-8 문자 사이 간격으로 고르게 분산하고, 문단 마지막 줄·페이지 마지막 줄은 왼쪽 정렬 유지. CJK (한국어) 는 문자 단위로 간격이 벌어지고, 영어는 대부분의 gap 이 공백 위치라 자연스럽게 단어 간 간격이 넓어지는 효과.

기술적 배경

측면이전 (1.2.0-ko.6)이후 (1.2.0-ko.7)
첫 진입 시간O(파일 크기), 1MB ~= 수 초, 40MB = 수 분O(1), 파일 크기 무관
메모리 사용pageOffsets 벡터 (페이지당 4 바이트)오프셋 + 256 항목 히스토리 스택
% 진행도페이지 번호 기반바이트 오프셋 기반 (정확)
N/M 페이지정확첫 페이지 샘플 기반 추정
캐시 파일 크기페이지 수에 비례고정 ~40 바이트
양쪽 정렬왼쪽 정렬로 폴백 (효과 없음)실제로 양쪽 끝 정렬
설정 변경 시 동작전체 파일 재스캔현재 오프셋 유지, 즉시 재렌더

사용자 영향

  • TXT 파일 열기가 파일 크기에 무관하게 즉시. 양쪽 정렬이 실제로 동작. 설정(폰트/여백/줄 간격 등) 변경 시에도 재스캔 대기 없음.
  • 한 번에 매우 깊이 뒤로 가기(256 페이지 이상) 시 이전 페이지 위치가 실제보다 한 페이지 이내로 어긋날 수 있음. 일반 독서에는 영향 없음.

v1.2.0-ko.6

1.2.0-ko.62026년 4월 20일
GitHub

요약

1.2.0-ko.5 에서 XTC 홈 화면 커버를 살렸지만 EPUB 홈 화면 커버가 첫 진입 시 제대로 안 뜨는 회귀가 생겼고, 일부 EPUB 에서 CSS 파싱 중 abort() 크래시가 관찰되어 수정합니다.
  1. EPUB 홈 커버 첫 시도 실패: 1.2.0-ko.5 의 빈 커버 폴백(fillRect + 아이콘)이 썸네일 파일이 없을 때 캐시된 프레임에 검은 픽셀을 남김. EPUB 썸네일은 1-bit BMP 라 drawBitmap1Bit 가 검은 픽셀만 그리고 흰 픽셀은 배경 그대로 두므로, 다음 렌더에서 커버의 흰 부분으로 이전 폴백의 검정이 비쳐 반전된 모양으로 나옴.
  2. CSS 파싱 크래시: 자동 생성된 수백 개 클래스가 있는 EPUB에서 heap 단편화 상태에서 unordered_map 재해시 실패로 bad_alloc → abort(). 첫 페이지는 렌더되지만 이후 페이지 넘길 때 ZIP inflate(~32KB) 할당이 실패.

한국어 버전 변경 사항

수정

  • EPUB 홈 커버 첫 진입 아티팩트 제거LyraTheme / Lyra3CoversTheme 가 썸네일 파일 부재 시 그리던 빈 커버 폴백을 되돌려 업스트림 동작에 맞춤. hasCover 는 이제 coverBmpPath 가 비었거나 BMP 파싱이 실패할 때만 false 가 됨. 디스크에 파일이 없으면 아무 것도 그리지 않고 썸네일 생성 후 다음 렌더에서 실제 커버가 표시됨.
  • HomeActivity 단순화 — 슬립 검증이 썸네일을 지우던 근본 원인은 1.2.0-ko.5 의 f47b549 에서 이미 수정되었으므로, 썸네일 생성 실패 시 coverBmpPath 를 비우는 구 업스트림 로직 제거. 이전 펌웨어가 coverBmpPath="" 로 저장해둔 SD 상태도 책 경로의 해시를 통해 복구 (Xtc/Epub 객체 인스턴스화 없이 해시 인라인).
  • CSS 파서 heap 안전장치processRuleBlockWithStyleloadFromCache 양쪽에 8 규칙마다 ESP.getMaxAllocHeap() 체크 추가. 48KB 이하로 떨어지면 파싱 중단. ZIP inflate(~32KB) + grayscale pass(~8KB) 에 필요한 연속 블록 확보. 부분 CSS 는 크래시/멈춤보다 낫다는 판단 — 스타일이 빠진 채라도 책이 정상 열림.

업스트림 미변경

업스트림 1.2.0 마스터 기준 파티션 레이아웃 유지 (OTA 호환 유지).

알려진 제한

  • 3.1M 픽셀을 초과하는 JPEG/PNG 이미지 (예: 1711×2507 표지)는 업스트림과 동일하게 디코딩 실패. 화면에 해당 이미지만 비게 표시되고 책 읽기는 정상.
30개의 릴리즈 중 7-9