TBD

아직 작성 중인 게시글입니다.

SaveBinaryCodec.cs
// Layout:
//   [0..4)              Magic       4 byte identifier
//   [4..6)              Version     uint16 LE (현재 2)
//   [6..8)              NumSections uint16 LE (N)
//   [8..8+44*N)         SectionTable[N], id 오름차순 정렬
//                          id:u16, flags:u16, offset:u32, len:u32, sectionHash:32B
//   [8+44*N..end-32)    Section payloads (raw bytes), 테이블 offset 순서대로 연속 배치
//   [end-32..end)       HeaderHash = SHA-256(magic..end-of-table)

그 외 짚어둘 디자인 결정들.

  • flags: u16 - 미래 확장 슬롯
    • 섹션 엔트리에 16비트 플래그를 둡니다. 현재 V2에서는 모두 0이지만, 섹션별 인코딩(예: 0x01 = gzip, 0x02 = encrypted)을 데이터로 표현할 자리를 미리 비워뒀습니다. 디코더가 플래그를 보고 동작을 분기하면 Version bump 없이 점진 확장이 가능합니다.
  • SectionId는 enum, 순서가 아닌 ID로 lookup
    • 페이로드를 “0번 섹션 = 세이브, 1번 = 로그” 식의 위치 기반으로 찾는 건 위험합니다. 섹션이 늘거나 빠질 때마다 디코더 측이 깨집니다. 항상 ID로 dict lookup을 강제합니다.

실구성

빌드한 게임에서 실제로 떨어진 save.bin을 hex로 까서 레이아웃이 의도대로 나오는지 검증해봤습니다. 파일 크기는 17058 bytes.

OffsetSizeContent
0..78 BMagic + v=2 + NumSections=2
8..5144 BSection[0]: id=1 SaveSnapshot, offset=96, len=14036, sectionHash 07ab9cdc...
52..9544 BSection[1]: id=2 EventLog, offset=14132, len=2894, sectionHash 731ffaad...
96..1413114036 BSaveSnapshot JSON UTF-8: {"Uid":"...":1}
14132..170252894 BEventLog jsonl: {"$type":"log-stat-set",...}\n{"$type":"log-buy-item",...}\n...
17026..1705732 BHeaderHash be1c4b14...