# CNS 조사 현황

## 결론

CNS 조사는 압축 해제, payload 분류, 필드/전투 배경 조립, 필드 충돌/occlusion
플래그 해석까지 확정했다. 게임 진행에 필요한 이벤트/전환/전투 연결은 아직 EXE 쪽
해석이 남아 있다.

현재 확정된 부분은 다음이다.

- `GENSE.FLD` 안의 377개 내부 파일은 모두 `.cns` 다.
- 377개 전부 압축 해제가 된다.
- payload 분류는 현재 unknown 없이 `image` 177개, `tilemap` 200개다.
- 이미지 CNS 는 팔레트 기반 PNG 로 변환 가능하다.
- 필드 맵 CNS 174개와 전투 배경 tilemap 26개는 웹 런타임 자산으로 내보낼 수 있다.
- 맵 tilemap 본문은 현재 `layer0[]` 뒤에 `layer1[]` 가 오는 planar 2레이어로 보는 해석이 맞다.
- 필드 맵 `layer1` 의 low 4비트는 방향별 충돌 플래그다. high 비트 중 `0x20` 은
  항상 그려지는 `map_*2` 전경 occlusion mask 이고, `0x10` 은 캐릭터 발 위치 의존
  foreground 플래그이며, `0x40` 은 EXE dirty redraw 소비 경로와 palette VM 근거가 있는
  animation redraw 플래그로 분리한다.
- `layer1` high 비트는 `0x20` 항상 foreground, `0x10` 조건부 foreground, `0x40`
  animation redraw 로 분리한다. 현재 불꽃/폭포/물결은 palette-only 로는 움직임이 맞지 않으며,
  0x40 dirty redraw 대상에 source-offset/row-cycle 같은 추가 animation stream 이 결합되는 구조로 보는 것이 더 맞다.
- `cara_at*`, `cara_rs*`, `cara_sm*` 같은 필드 캐릭터 걷기 프레임은 폭 48px,
  즉 16px 타일 3칸 구조다. 이동/충돌 판정은 전체 48x64 스프라이트 박스가 아니라
  하단 3x1 타일 발판을 기준으로 한다.

## 완료 기준

이 문서에서 CNS 완료로 보는 범위는 다음으로 고정한다.

| 범위 | 완료 기준 |
| --- | --- |
| 압축 해제 | 377개 CNS 전부 decode 가능 |
| payload 분류 | image 177개, tilemap 200개, unknown 0개 |
| 이미지 변환 | UI/title/tile/sprite 계열을 PNG 로 변환 가능 |
| 필드 맵 조립 | 174개 필드 맵을 `layer0` + `map_*1` 로 조립 가능 |
| 전투 배경 조립 | 26개 `btl_*` tilemap 을 전투 배경으로 조립 가능 |
| 필드 충돌 | `layer1` low 4비트를 방향별 통행/충돌 플래그로 사용 |
| 캐릭터 발판 | 48px 폭 필드 캐릭터의 하단 3x1 타일 발판을 이동/충돌 기준으로 사용 |
| 필드 가림 | `layer1` `0x20` 칸은 항상 `map_*2` foreground 로 overlay, `0x10` 은 캐릭터 발 위치 기준으로 조건부 overlay |
| 투명색 | 이미지/타일셋별 key color 를 적용해 PNG 와 canvas 렌더링에서 투명 처리 |

아래 항목은 CNS 파일 자체가 아니라 EXE/event VM 또는 런타임 상태 해석 영역이다. CNS 완료
판정에 포함하지 않는다.

| 범위 | 이유 |
| --- | --- |
| 맵 전환/출입구 | tilemap payload 에 목적지 맵/스폰 좌표가 들어 있지 않다. |
| 시나리오 진행 조건 | scene/event/object VM 쪽 조건 해석이 필요하다. |
| 대사 재생 순서 | CNS plain CP949 텍스트 후보가 없어 EXE/event stream 쪽 근거가 필요하다. |
| 원본 전투 진입/공식 | 전투 배경 CNS 는 조립됐지만 전투 루프/AI/수치는 별도 EXE 영역이다. |
| 저장 지점 UI | 저장 지점 후보는 event/object 실행 조건과 메뉴 호출 흐름이 필요하다. |

아직 끝나지 않은 부분은 다음이다.

- 맵 전환 trigger 와 spawn 좌표의 원본 이벤트 근거
- 대화/상호작용/event VM 전체 의미
- 원본 전투 진입, 적 데이터, 전투 공식
- save point 이벤트(여관/석상/회복 NPC)와 저장 UI 호출 조건
- 일부 scene table 의 같은 맵 다른 tileset variant 가 실제 어느 시점에 쓰이는지

따라서 CNS 파일은 대부분 게임 진행에 필요한 핵심 리소스가 맞지만, "파일 포맷을 읽는다"와
"그 파일을 원작처럼 진행 로직에 연결한다"는 아직 다른 단계다. 지금은 전자는 꽤 진행됐고,
후자는 계속 reverse engineering 중이다.

## 현재 분류

`out/cns_payloads.json` 기준:

| 분류 | 개수 | 현재 사용/의미 |
| --- | ---: | --- |
| field maps | 174 | `map1_01a.cns` 같은 필드 맵 tilemap. 웹 맵 chunk 로 사용한다. |
| battle backgrounds | 26 | `btl_*` 전투 배경 tilemap. 전투 검토 화면에서 사용한다. |
| map tilesets | 45 | `map_a1.cns` 같은 16x16 타일셋 이미지. 필드/전투 배경 렌더링에 필수다. |
| character sprites | 37 | `cara_*` 캐릭터/동료/NPC 스프라이트 리소스. |
| battle sprites | 8 | `btl_at.cns`, `btl_sm.cns` 같은 전투 캐릭터 스프라이트. |
| face sprites | 1 | `face_01.cns` 얼굴 리소스. |
| enemy/object sprites | 65 | `z*`, `boss_*` 계열 적/오브젝트 스프라이트 리소스. |
| UI/title/misc images | 21 | 타이틀, 창, 아이콘, 숫자, 아이템, 상태 UI 등. |

payload 종류별로는:

| payload kind | 개수 | 산출물 |
| --- | ---: | --- |
| `image` | 177 | PNG 변환, 웹 이미지 asset |
| `tilemap` | 200 | 필드 맵/전투 배경 tilemap |

## 주요 정리 자료

| 파일 | 내용 |
| --- | --- |
| `docs/CNS_FORMAT.md` | CNS 압축 방식, 이미지 payload, tilemap payload, 현재 coverage. |
| `docs/FORMATS.md` | 전체 데이터 포맷 문서. `GENSE.FLD` 와 CNS, scene/event/save 관련 맥락 포함. |
| `out/cns_payloads.json` | 377개 CNS 전수 분류. image/tilemap, 크기, decoded bytes. |
| `out/map_tileset_candidates.md` | 각 필드 맵이 어떤 tileset 묶음을 쓰는지: filename suffix, EXE scene record, condition payload 비교. |
| `out/scene_manifest.json` / `.md` | EXE 안의 field map scene record 와 주변 resources/tilesets/sprites. |
| `out/cns_text_candidates.html` / `.json` | CNS payload 내부 plain CP949 텍스트 스캔. 현재 후보 0개. 대사는 CNS plain text 가 아니라 EXE/event stream 쪽으로 보는 근거다. |
| `web/map_review.html` | 필드 맵 layer0, 충돌 low bits, `0x20` foreground, `0x10` 조건부 foreground, `0x40` animation redraw 위치를 직접 검토하는 현재 화면. |
| `web/map_occlusion.html` | 캐릭터를 직접 움직이며 `0x20` 항상 foreground, `0x10` 조건부 foreground, 방향 edge 충돌을 함께 확인하는 화면. |
| `web/map_gallery.html` | 확정된 필드 맵 조립 결과를 map0*~map8* 순서로 훑어보는 갤러리. |
| `web/field_character_review.html` | `cara_at1`/`cara_rs1`/`cara_sm1` 48x64 보행 프레임, 방향별 애니메이션, 하단 3x1 충돌 발판을 검토하는 화면. |
| `web/battle_background_review.html` | 전투 배경 tilemap 조립 결과 검토 화면. |
| `web/ui_grid_review.html` | `item.cns` / `icon.cns` 32x32 격자와 EXE item/action meta 매핑 검토 화면. |
| `web/ui_window_review.html` | `ui-misc` 전체(`01234567`, `aaa`, `compile`, `ds14_*`, `ed*`, `frame`, `icon`, `item`, `logo_00`, `num`, `p_*`, `spot`, `status`, `sun`, `title`, `window`)와 `btl_etc`, `face_01`, `cara_fnt` 단위 검토 화면. |
| `out/cns_precut_catalog_review.html` / `.json` | EXE 기준 CNS 접근 방식을 `descriptor +4 source-rect catalog`, `window template/region`, `fixed grid`, `unbound candidate`로 분리한 리뷰. |

`frame.cns` 는 640x352 단일 화면 프레임 오버레이로 확정한다. 테두리 영역을 제외한
대부분의 픽셀은 CNS palette index 0 투명색이며, 조각으로 나누거나 9-slice로 조립하지
않는다. `web/ui_window_review.html` 은 `window.cns`, `status.cns`, `num.cns`, 아이콘/아이템
sheet, 전투 표시 조각, 오프닝/타이틀/엔딩/문구 계열 `ui-misc` CNS 단위를 계속 비교하기 위한 작업대다. 몬스터와
필드 캐릭터 프레임은 각각 `web/monster_review.html`, `web/field_character_review.html` 로
분리되어 있으며 예전 통합 `monster_grid_review.html` 은 현재 검토 화면으로 쓰지 않는다.

## 구현 도구

| 도구 | 역할 |
| --- | --- |
| `tools/decode_cns.py` | CNS 압축 해제 및 이미지 PNG 변환. |
| `tools/classify_cns_payloads.py` | 377개 CNS payload 를 image/tilemap 으로 분류. |
| `tools/export_map_js.py` | CNS 맵을 웹 런타임용 JS/chunk 로 내보냄. |
| `tools/build_web_assets.py` | 현재 웹 런타임에 필요한 CNS 기반 asset 전체 생성. |
| `tools/render_map_preview.py` | 맵 preview PNG 생성 및 현재 리뷰 보조 렌더링. |
| `tools/probe_exe_cns_groups.py` | EXE 안의 CNS 파일명 묶음 탐색. |
| `tools/extract_scene_manifest.py` | EXE scene record 와 CNS resource 묶음 추출. |
| `tools/summarize_cns_text_candidates.py` | CNS 내부 plain CP949 텍스트 후보 스캔. |
| `tools/build_cns_precut_catalog_review.py` | EXE의 CNS descriptor +4 rect table과 window template/region catalog를 분리해 요약. |

## 웹 런타임에서의 사용 상태

- `/web/index.html` 은 전체 `out/maps.js` 를 바로 로드하지 않고 `out/maps_runtime.js` 와
  `out/maps_runtime_chunks/*.js` 를 통해 필요한 맵 chunk 만 로드한다.
- 현재 필드 맵 174개는 모두 `out/maps.js` 분석용으로 들어가고, 진행/검토에 필요한 맵은
  runtime chunk 로 분리된다.
- `out/maps_runtime_chunks/map1_02b.js`, `map1_01a.js`, `map2_02d.js` 같은 chunk 는
  현재 routeAssist/playtest 경로에서 바로 쓰인다.
- 타일셋 PNG, 캐릭터 PNG, 전투 배경 JS, 전투 캐릭터 스프라이트가 웹에서 사용된다.

## 남은 핵심 리스크

CNS 자체를 읽는 문제보다, CNS 와 EXE event/object VM 을 연결하는 문제가 더 크다.
현재 가장 큰 route blocker 인 `map1_01a -> map2_02d` 도 CNS 파일은 이미 읽히고
맵/타일셋도 렌더링되지만, 이 전환을 원작 normal route 로 승격할 strict source hotspot 또는
runtime trace proof 가 없다.

즉 다음 작업은 새 CNS 디코더를 만드는 것이 아니라, 이미 읽힌 CNS 리소스를 어떤 원본 이벤트가
언제 로드하고 어떤 좌표/상태에서 실행하는지 증명하는 쪽이다.
