CLI
초판 분석 기준: 공식 저장소 ID 1416502082, 커밋 93578abad6704ae95fbf60e80027469f145b02cf. README·개발 문서와 rewriter·loader·그래픽 번역기·iOS 프로젝트·테스트 코드를 읽었습니다. 게임, 키, 빌드 도구를 설치하거나 실행하지 않았으며 성능과 호환성은 제작자의 보고와 코드 관찰을 구분합니다.
이번 관측 커밋 7a3b95873bf1836bf7f70e2e2e3245e1cabb1620은 --platform mac-app 경로를 추가합니다. Apple silicon Mac에서 호스트·변환 모듈·RomFS·셰이더를 .app으로 묶고, Finder에서 실행하는 런처를 포함합니다. 기존 개발용 Mac 실행·iOS IPA·Xcode 프로젝트는 별도 경로입니다.
dm/mac/pack_app.py는 .partial 디렉터리에서 패키징하고 성공할 때 기존 앱과 교체합니다. 같은 APFS 볼륨에서 clone 가능성을 시험한 뒤 큰 리소스를 복제하고, 불가능하면 실제 복사 용량과 여유 공간을 확인합니다. host를 먼저 서명하고 bundle을 서명하며 기본은 ad-hoc입니다. hardened runtime을 사용하지 않아 공증할 수 없다는 제약도 소스에 적혀 있습니다.
dm/mac/launcher.c는 Info.plist의 DMModuleFiles 목록으로 모듈·표 누락을 확인합니다. 오류 메시지를 AppleScript 문자열 안에 직접 끼워 넣지 않고 argv로 전달합니다. 세이브는 ~/Library/Application Support/nxnative/<title-id>/save/, 로그는 ~/Library/Logs/nxnative/로 분리합니다.
README의 게임 갤러리는 이제 Mac 또는 iPhone에서 시험한 목록입니다. 갤러리 등재를 iPhone 검증 완료로 읽으면 안 됩니다. ASTRAL CHAIN·Ghost Trick 프로필과 프레임 버퍼링 선택도 추가됐으며, 목록·성능·문제는 게임별 노트를 기준으로 봅니다. 이번 분석은 실행 검증을 하지 않았습니다.
아래 본문은 최초 분석 93578aba의 소스·프로필·측정 범위를 보존했습니다. 이후 16f4889192dd9bc6363a77b5d8b9654fe65441a2까지의 변경을 추가로 읽었습니다. Mac·Xcode·호환 Apple 단말과 입력 자료·서명이라는 기존 조건은 같습니다. 게임·키를 사용하거나 빌드·실행·성능 측정을 하지는 않았습니다.
uepak.py와 shader_split.py는 별도 셰이더 아카이브 없이 패키지 안에 코드가 들어 있는 Unreal v11 pak도 구분해 읽고 Zlib/LZ4 블록을 처리합니다. pak의 버전 숫자만으로 모든 셰이더 저장 방식을 가정하지 않습니다.nvn_refl.h의 셰이더 바인딩 상한은 64에서 96으로 늘고, 사전 컴파일 탐색 뒤 scissor 상태를 복원합니다. 큰 지오메트리 draw는 지원하는 목록 토폴로지에서 나눠 처리하고 인덱스를 세 단계 dispatch로 압축합니다. strip·fan·primitive restart는 분할 대상이 아니며, 분할된 primitive ID의 한계도 남아 있습니다.hle_uemalloc.c와 hle_svc.c는 호스트 Unreal 할당자를 쓸 때 게스트 블록 밖에 있는 읽기·쓰기 가능한 스레드 스택의 매핑을 처리합니다. 스크립트 입력에는 스틱을 일부만 기울이는 표현이 추가됐습니다. 이 변경이 모든 게임의 메모리·입력 호환성을 보장하지는 않습니다.근거: 게임 프로필의 확인 범위·남은 문제, 셰이더 변경·제약 기록. 새 이미지는 사용하지 않았습니다.
승인 기준 16f4889192dd9bc6363a77b5d8b9654fe65441a2 이후부터 관측 커밋 c1b7eff61fb3ca2d182320f12a9c6c30dc3c520e까지 README·개발 문서·게임 노트와 관련 소스를 대조했습니다. 빌드·게임·GPU 테스트는 실행하지 않았습니다. 아래 측정·실행 결과는 제작자의 기록이며 독립 재현 결과가 아닙니다.
nvn_mtl.m의 blit_buf는 별칭 가시성 플래그를 켜고, hle_nvn.c의 nvn_sparse_alias가 sparse 범위와의 겹침을 찾으면 복사를 보수적으로 앞뒤 연산과 순서화합니다. 일반 풀의 범위 기반 묶음 처리는 유지합니다. 주소 범위가 다르다는 사실만으로 독립적인 복사라고 판단하지 않는 수정입니다.nvn_imga_layout.h는 곱셈 오버플로·버퍼 길이·오프셋·행 간격을 검사합니다. IMG 텍스처와 원자 연산용 IMGA 버퍼의 짝이 모호하거나 지원하지 않는 직접 뷰이면 draw/dispatch 전에 진단과 함께 멈춥니다. 비선형 이미지의 기존 discard scratch는 이미지와 일관된 저장소로 바뀐 것이 아닙니다. 이 제한을 일반적인 호환성 보장으로 읽으면 안 됩니다.nso_match.py는 명시적으로 허용한 패치만 함수 전체·직접 호출 대상의 지문으로 대조합니다. 단순 바이트 검색이나 유사도 매칭이 아니며, 주소 재배치만 정규화합니다. 코드가 같다는 근거와 새 게임 버전에도 우회 수정이 필요하다는 판단은 별개입니다.dm/ios/tools/build_smoke.py가 작은 합성 모듈과 XcodeGen으로 전체 iOS 앱을 컴파일·링크한다고 설명합니다. 게임·키 없이 빌드 결합을 확인하는 경로이며, 서명·설치·게임 실행 검사는 하지 않습니다.원본: Metal 복사·수명 코드 · IMG/IMGA 계약 · 함수 대조 코드 · 메모리 변경 기록 · 스레드 handoff · NieR 검증·미확인 범위 · 개발·합성 빌드 문서.
nxnative는 Switch의 ARM64 실행 코드를 Apple ARM64에서 실행하도록 사전 변환하고, Horizon 운영체제 서비스와 NVN 그래픽을 대신 구현해 게임별 iOS IPA를 만드는 도구입니다. 사용자가 제공한 게임 파일과 키를 입력으로 삼는 패키징 경로가 있으며, 저장소에는 게임 자체가 없다고 README가 명시합니다.
README의 “에뮬레이터가 아니다”는 표현은 CPU 명령어를 매번 해석하는 대신 게임 코드를 직접 실행한다는 뜻으로 읽어야 합니다. 운영체제와 GPU까지 원래대로 실행한다는 뜻은 아닙니다. 실제 dm/host/hle_*.c는 커널·파일·입력·오디오 등의 동작을 대체하고, dm/gfx는 그래픽 호출을 Metal로 재구현합니다.
| 판단 항목 | 내용 |
|---|---|
| 적합한 독자 | ARM64 바이너리 호환성, 시스템 호출, 그래픽 번역, iOS 서명 제약을 실제 코드로 공부할 개발자 |
| 사용 흐름 | Mac에서 게임별 코드·셰이더·프로필을 준비 → IPA 생성 → 사용자가 별도로 서명·설치 |
| 기대하면 안 되는 것 | 모든 Switch 게임 지원, 온라인 기능, 원본과 동일한 렌더링, 내려받아 즉시 실행하는 통합 게임 라이브러리 |
| 배포 조건 | 프로젝트는 MIT, 포함된 외부 코드는 각 라이선스 유지. 이 라이선스는 사용자가 가져온 게임·키의 권한을 제공하지 않음 |
기술적으로 흥미로운 지점은 세 가지입니다. 첫째, Switch와 Apple 기기가 같은 AArch64 계열이라는 공통점을 이용하되 서로 다른 ABI와 시스템 환경만 변환합니다. 둘째, Maxwell GPU 셰이더를 오프라인에서 SPIR-V와 Metal 라이브러리로 바꿔 단말에서 처리할 일을 줄입니다. 셋째, 게임별 예외를 공통 호스트에 무작정 섞는 대신 프로필과 build ID에 연결합니다.
기존 CPU 에뮬레이션을 쓰는 도구와 비교하면, 이 프로젝트의 학습 가치는 “모든 하드웨어를 가상화하는가”보다 어떤 연산은 그대로 두고 어떤 경계만 대체할 수 있는가에 있습니다. 그렇다고 성능 우위를 일반화할 수는 없습니다. README의 플레이 가능·60fps 목록은 특정 기기·게임 버전에 관한 제작자 보고이며 이 분석에서 재측정하지 않았습니다.
코드의 출발점도 중요합니다. README는 jhaizhou-ops/d2r-mobile의 범용 부분을 복사해 시작했고 수정이 양방향으로 오간다고 밝힙니다. Ryujinx는 셰이더 번역 라이브러리로 포함됩니다. 전체 Ryujinx 앱을 iOS에 옮긴 프로젝트로 이해하면 구조를 놓칩니다.
| 층 | 기술 / 파일 | 책임 |
|---|---|---|
| 파이프라인 | Python, scripts/build_ipa_from_nsp.py | 입력 식별, 단계 실행·재사용, 진행 이벤트와 실패 로그 관리 |
| 실행 파일 변환 | Python·Capstone·LZ4, dm/tools/patch_nso.py | NSO/NRO 읽기, ARM64 명령어 분석, 패치·gate·재배치 표 생성 |
| 운영체제 호스트 | C·ARM64 어셈블리·Objective-C, dm/host | 모듈 로딩, 스레드 로컬 상태, 동기화, 파일·입력·오디오 서비스 |
| 그래픽 | NVN/Vulkan/OpenGL 호환 층, Objective-C·Metal | 게스트 명령 기록·재생, 버퍼·텍스처·GPU 완료 상태 관리 |
| 셰이더 도구 | C#/.NET·Ryujinx → SPIR-V → SPIRV-Cross → Metal 컴파일러 | Maxwell 셰이더를 기기에서 로드할 Metal 라이브러리와 reflection JSON으로 변환 |
| 앱 화면 | Swift/SwiftUI·UIKit·GameController, dm/ios | 실행 전 설정, 터치·물리 컨트롤러, 앱 생명주기 |
| 빌드 인프라 | Xcode·XcodeGen·Make·셸, vendored 외부 소스 | 호스트와 변환 코드를 묶고 게임별 리소스를 패키징 |
클라우드 백엔드나 모델 API가 필요한 구조는 아닙니다. 대신 Mac의 개발 도구, 상당한 저장 공간, 호환 Apple 단말, 사용자의 입력 자료가 필요합니다. 외부 코드를 저장소에 함께 둔다고 해서 Xcode·.NET 등 전체 도구까지 포함되는 것은 아닙니다.
patch_nso.py의 머리 주석은 변환 대상을 구체적으로 적습니다. Apple 커널이 사용하는 x18, 서로 다른 스레드 포인터 레지스터, svc 시스템 호출, 타이머 읽기, 스택 정렬을 보정합니다. 예를 들어 Horizon의 스레드 상태를 Apple의 pthread TSD(Thread-Specific Data)에 대응시키고, 시스템 호출 지점을 호스트의 gate로 연결합니다. 명령어 집합이 같아도 프로세스가 기대하는 주변 계약이 다르기 때문입니다.
공통 변환과 특정 빌드 수정은 구분됩니다. sdk_patches.py와 게임별 patches.py의 CUTS는 build ID에 연결되며, 같은 build ID가 중복 등록되면 멈춥니다. 아래는 실제 검사 부분입니다.
# dm/tools/patch_nso.py:80-85
BUILD_ID = d[0x40:0x50].hex()
cuts = list(PATCHES['CUTS'].get(BUILD_ID, []))
for off, ob, nb, why in cuts:
ob, nb = bytes.fromhex(ob), bytes.fromhex(nb)
assert len(ob) == len(nb) and IMG[off:off + len(ob)] == ob, \
f'cut original bytes mismatch {off:#x}: {bytes(IMG[off:off + len(ob)]).hex()}'
IMG[off:off + len(nb)] = nb
이 검사는 다른 버전의 코드를 같은 오프셋이라는 이유만으로 덮어쓰는 사고를 막습니다. 모든 변환 결과의 정확성을 증명하는 검사는 아닙니다. 개발 문서는 등록되지 않은 게임 버전도 해당 버전의 입력에서 파생 프로필을 만들 수 있지만, 검증된 버전용 수정은 다른 build ID에 적용하지 않는다고 설명합니다.
loader.c는 모듈 매핑·스레드 슬롯·gate 등록·심볼 재배치·세그먼트 권한을 맡습니다. 머리 주석은 코드와 패치 영역을 복사한 뒤 읽기/실행 권한으로 고정하고 이후에는 데이터만 쓴다고 명시합니다. iOS에서는 이 코드가 서명된 실행 세그먼트에 들어가야 합니다. 단순히 다운로드한 ARM64 파일을 앱 실행 중 임의로 붙이는 설계와는 다른 제약입니다.
dm/gfx/README.md에서 nvn/hle_nvn.c는 인터페이스·명령 기록, nvn/nvn_mtl.m는 제출 시 재생을 담당합니다. 게스트가 GPU 완료를 관측하는 시점은 Metal command buffer가 실제 끝난 뒤여야 합니다. CPU가 빨리 돌아가더라도 동기화 의미가 틀리면 렌더링과 게임 상태가 어긋납니다.
셰이더 번역기 dmsh_xlate/Program.cs는 코드만으로 알 수 없는 텍스처 차원·출력 타입·작업 그룹 크기를 프로필의 shader_facts.tsv에서 공급받습니다. 번역 체인 해시는 라이브러리 디렉터리와 reflection에 기록되고 호스트가 불일치한 결과를 거부합니다. 캐시를 빠르게 만드는 것과 잘못된 캐시를 쓰지 않는 것이 함께 설계돼 있습니다.
커밋 9bdef355ab3254d9a39f074f032ba41a2092705b에서는 첫 실행 설정을 Game·Controls·Performance 한 화면으로 묶고, 사용자가 기본값과 다르게 선택한 값만 저장합니다. 새 빌드의 기본값은 별도 선택이 없던 설정에 반영되며, Documents/env.txt가 화면보다 우선합니다. docs/settings.md가 이 우선순위와 초기화 동작을 설명합니다.
MetalFX 업스케일링은 선택 기능입니다. nvn_mtl.m은 Metal 4 큐와 GPU 지원을 확인하고, 지원하지 않는 기기·크기는 기존 보간으로 처리합니다. 그림을 키울 때 GPU 시간·발열 비용이 추가되며, 문서는 iPhone에서 Standard와 비교한 동일 조건의 열 비용은 아직 측정하지 않았다고 밝힙니다.
빌드 스크립트는 이전 빌드에서 번역됐던 셰이더가 새 변환 체인에서 실패하면 기본적으로 중단합니다. shader_regressions.py는 같은 게임의 이전 빌드 보고와 현재 보고에서 성공→실패가 된 키를 대조하고, logs/shader_regressions.log에 남깁니다. 이전 보고가 없거나 한쪽에 키가 없으면 회귀로 세지 않으므로 모든 셰이더의 정확성을 보장하는 검사는 아닙니다.
# 현재 빌드 설정의 기본값 (실행 예제가 아닌 코드 발췌)
ALLOW_SHADER_REGRESSIONS = False
# 기존 성공 셰이더가 실패하면 BuildError
# --allow-shader-regressions는 누락된 셰이더를 포함하지 않고 진행하는 예외
PSO_GPUS / --gpu로 GPU별 파이프라인 기반 아카이브도 미리 만들 수 있습니다. iOS 기본 선택은 게임 프로필의 Metal 4 설정에 따르고, Mac 앱은 로컬 GPU를 기본으로 합니다. 처음 실행 때의 준비를 줄이는 대신 패키지 크기·첫 빌드 시간이 늘어납니다. Homebrew의 .NET 런타임 위치를 찾아 DOTNET_ROOT를 맞추는 처리와 NSZ 입력의 키 파일 전달도 수정됐습니다.
새 Xenoblade Chronicles 3 2.2.1 프로필은 Mac의 초반 전투·이동 확인과 iOS 빌드 성공을 구분해 기록합니다. iOS 실제 실행·후반 메모리 최대치·DLC 렌더링은 미검증입니다. 패키지가 만들어졌다는 이유만으로 단말 호환을 확정하지 않습니다.
이번 소스는 7e0f59712b0cad3101543b47c06bd76150f845b6입니다. Mac 앱은 시작 전에 자체 설정창을 표시하고, Finder·Dock·외부 프런트엔드가 같은 preferences 저장소의 launcher.<env> 문자열을 사용합니다. 실행 환경 → 사용자 env.txt → 번들 env.txt → 저장 선택 → 테스트 기본값 순으로 먼저 설정한 값이 이깁니다. DM_LAUNCHER=0은 창만 건너뛰며 저장 선택은 적용하고, DM_SAVED_CHOICES=0은 저장 선택 적용을 건너뜁니다.
dm/games/settings.py는 launcher.json에 schema:1을 씁니다. base는 렌더 스케일의 docked/handheld 기준 크기, level은 첫 화면 우선 표시, needs는 상위 설정값에 따른 하위 항목 조건입니다. schema 1은 선택 필드만 늘리고 알 수 없는 필드는 무시하는 계약이며, 새 kind는 schema 2가 필요합니다.
게임 프로필·settings.tsv
→ settings.py → launcher.json / Info.plist의 DMSettings
→ 앱 설정창 또는 별도 프런트엔드
→ 동일 preferences → launcher.c의 값 검사 → 게임 실행
README가 안내하는 NX2Apple은 nxnative 위에 구축한 별도 커뮤니티 Mac 앱입니다. 현재 호스트 로그는 사람용 진단 문자열이며 안정된 실행 이벤트 API로 보장하지 않습니다. 빌드 JSON 이벤트는 종료 코드·stderr와 함께 읽어야 합니다.
압축 NSZ/XCZ 입력은 현재 Python의 nsz 패키지가 없을 때 PATH의 nsz 또는 nsz-cli-macos-arm64 실행파일도 찾습니다. 독립 실행파일은 --keys 지원을 검사하므로 nsz 5.0+가 필요합니다. 임시 출력은 성공과 파일 존재를 확인한 뒤 옮깁니다. 이 분석에서는 입력 게임·키나 변환 도구를 실행하지 않았습니다.
고정 소스 6c4a81d40d200bbfe65ad0027ab093405367ada6는 --romfs separate로 게임 데이터 RomFS를 IPA에서 분리하는 경로를 제공합니다. 기본은 bundle이며, 분리하면 앱 재빌드마다 대용량 게임 데이터를 다시 묶거나 전송할 필요가 줄어듭니다. 게임 데이터·키는 사용자가 직접 제공해야 하고 저장소에는 들어 있지 않습니다.
# 별도 입력 자료와 로컬 개발 환경이 준비된 독자용 예시
python3 scripts/build_ipa_from_nsp.py ~/Games/MyGame \
-k ~/keys/prod.keys --romfs separate
빌드가 출력한 scripts/push_romfs.sh 명령으로 해당 게임 버전의 데이터를 한 번 복사합니다. 앱은 자신을 빌드한 이미지와 데이터의 정체성이 맞는지 확인하므로 다른 버전의 RomFS를 이름만 바꿔 재사용하는 흐름이 아닙니다.
README의 현재 기준은 macOS 26.6+·Xcode 27.1·arm64 Python 3.12+입니다. 첫 빌드 시간과 디스크 여유 수치는 제작자 안내이며 기기·게임·캐시에 따라 달라집니다. 실습은 먼저 Python 스크립트의 ROMFS 기본값·인수 파싱·출력 경로를 읽고 bundle/separate의 데이터 배치를 비교하는 것으로 시작합니다. 이 분석에서 변환·서명·게임 실행을 수행하지 않았습니다.
근거: 빌드 입력과 RomFS 선택 · 별도 데이터 전송 절차. 앞선 날짜의 설정·프런트엔드 계약은 각 블록의 SHA를 보존합니다.
nxnative/
├─ scripts/build_ipa_from_nsp.py 단계 조율·진행 이벤트
├─ dm/
│ ├─ tools/ 실행 파일 분석·rewrite
│ │ └─ tests/ 패키징·진행·패치 회귀 사례
│ ├─ host/ loader·Horizon 서비스·단말 IO
│ │ └─ tests/ 메모리·로더 등 합성 테스트
│ ├─ gfx/
│ │ ├─ nvn/ NVN 인터페이스와 Metal 재생
│ │ ├─ vk/ · gl/ 다른 그래픽 API의 호환 층
│ │ └─ tools/ 셰이더 분리·번역·캐시 체인
│ ├─ games/ title ID별 프로필·빌드별 수정
│ ├─ ios/ XcodeGen·앱 셸·패키징 도구
│ └─ third_party/ 출처·라이선스가 함께 든 외부 소스
└─ docs/ development·reference·agents
처음에는 개별 게임의 긴 셰이더 표보다 patch_nso.py 머리 주석 → loader.c → dm/gfx/README.md 순으로 읽는 편이 낫습니다. docs/reference는 스레드·서비스·메모리·렌더링 주제를 보충하고, docs/agents는 bring-up과 고장 증상을 연결합니다. 외부 문서의 에이전트 지시문은 이 분석을 위한 실행 권한으로 취급하지 않았습니다.
| 배울 주제 | 코드 근거 | 확인할 질문 |
|---|---|---|
| 바이너리 변환 | patch_nso.py의 branch 범위·패치 영역·원본 검증 | 변환한 분기가 원래 코드로 돌아갈 수 있는가? 큰 BSS가 주소 배치에 어떤 영향을 주는가? |
| ABI 호환 | loader.c의 TSD 검증, gfx/README.md의 좁은 정수 인자 설명 | 같은 ARM64 호출이라도 레지스터·인자·스택 계약이 어디서 다른가? |
| 메모리 모델 | docs/development.md Guest memory SVCs | 논리적 4KiB 구간을 16KiB 호스트 페이지 위에서 어떻게 보존하는가? |
| 그래픽 번역 | dmsh_xlate/Program.cs, shader_facts.tsv | 명령어에 없는 타입·차원 정보를 누가 제공하는가? |
| 재현 가능한 캐시 | gfx/README.md의 translation chain version | 툴·프로필·입력이 바뀌었을 때 어느 산출물을 다시 만드는가? |
| 운영 가능한 CLI | test_nsp_progress.py | 작업량을 모를 때 null·추정치·실패 로그를 어떻게 UI에 전달하는가? |
| 단계 | 확인된 조건 |
|---|---|
| 소스 학습 | Git·텍스트 편집기, 아래 정적 실습에는 Python 표준 라이브러리만 필요. 게임·키·Apple 기기 불필요 |
| IPA 빌드 | README 기준 macOS 26.6+·Xcode 27.1·arm64 Python 3.12+·Homebrew. xcodegen·zstd·glslang·.NET SDK와 lz4·capstone·fonttools·nsz 등이 필요하며 Python 3.14 미만에는 backports.zstd도 필요합니다. SPIRV-Cross는 저장소 안에서 빌드합니다. |
| 단말 | README 기준 iOS/iPadOS 26+, iPhone 15 Pro(A17 Pro) 이상 또는 M1 이상 iPad. BC 압축 텍스처 지원이 이유 |
| 그래픽 제약 | NVN 경로는 통합 메모리와 Metal 4를 사용. project.yml의 iOS 배포 대상도 26.0 |
| 저장 공간·시간 | README 추정 여유 공간은 입력 NSP 크기의 약 2배+10GB, 첫 빌드 30~60분·호스트만 바뀐 후속 빌드는 약 1분. 게임·Mac·캐시에 따라 달라지며 미측정 |
| Mac 앱 | Apple silicon·Mac용 빌드 도구와 입력 리소스. --platform mac-app으로 .app을 만들며 hardened runtime·공증은 지원하지 않음 |
| 서명·메모리 | 별도 사이드로딩/서명 경로 필요. README는 Increased Memory Limit capability 유무가 큰 게임의 실행에 영향을 준다고 명시 |
| 비용·라이선스 | 프로젝트 사용료나 모델 API 의존은 제시되지 않음. 기기·게임·서명 계정 등 사용자가 선택하는 외부 비용은 별개. MIT 및 third_party 고지 유지 |
README의 지원 목록 밖 게임은 잠정 설정으로 IPA가 만들어져도 실행되지 않을 수 있습니다. 알려진 한계에는 amiibo·온라인 기능 부재와 특정 게임의 소리·그래픽 결함이 있습니다. MIT라는 사실을 모든 입력 게임이나 변환 결과의 재배포 허가로 확대해서는 안 됩니다.
공식 저장소를 확보한 로컬 디렉터리에서 다음 읽기 명령을 실행합니다. git show는 현재 체크아웃 상태와 무관하게 지정 커밋의 파일을 읽습니다.
PIN=93578abad6704ae95fbf60e80027469f145b02cf
git cat-file -t "$PIN"
git ls-tree --name-only "$PIN"
git show "$PIN:docs/development.md"
완료 기준: 첫 결과가 commit인지 확인하고, 개발 문서에서 빌드 시점과 단말 실행 시점의 일을 각각 세 개 적습니다. 객체가 없으면 현재 HEAD를 같은 분석 대상으로 간주하지 않습니다.
git show "$PIN:dm/tools/patch_nso.py"
git show "$PIN:dm/host/loader.c"
BUILD_ID·CUTS·cut original bytes mismatch와 tsd_check를 찾습니다. 완료 기준: ① 다른 build ID, ② 같은 ID인데 원본 바이트 불일치, ③ Apple TSD 배치 불일치가 각각 어디서 처리되는지 파일과 조건으로 기록합니다. 실행 파일을 수정하거나 키를 준비할 필요가 없습니다.
git show "$PIN:dm/gfx/README.md"
git show "$PIN:dm/gfx/tools/dmsh_xlate/Program.cs"
완료 기준: 입력·도구·출력을 Maxwell → SPIR-V → MSL → metallib 네 칸에 채우고, translation chain version 불일치와 게임 프로필 변경을 구분합니다. 같은 GPU 코드라도 텍스처 차원 정보가 빠지면 왜 기본값으로 안전하게 처리할 수 없는지 설명합니다.
git show "$PIN:dm/tools/tests/test_nsp_progress.py"
테스트 Json.test_events에서 기대 이벤트 순서를 읽어 작은 상태 전이 표를 만듭니다. 완료 기준: stage·progress·stage_end를 구분하고, 작업량 미상인 null과 실패한 ok:false를 화면에 어떻게 나타낼지 정합니다. 외부 게임 입력 없이 파이프라인 UI의 계약을 공부할 수 있습니다. 테스트를 실제 실행했다는 뜻은 아닙니다.
PIN=7e0f59712b0cad3101543b47c06bd76150f845b6
git show "$PIN:docs/frontends.md"
git show "$PIN:dm/games/settings.py"
git show "$PIN:dm/mac/launcher.c"
완료 기준: 알 수 없는 선택 필드와 kind를 구분하고, 저장된 값이 새 빌드의 선택지에 없을 때의 처리, 두 DM_* 스위치의 차이를 적습니다. 앞의 초판 고정 예제와 이번 커밋을 구분합니다.
| 주차 | 읽기와 산출물 |
|---|---|
| 1주 | AArch64 호출 규약·NSO 세그먼트·ELF 심볼을 정리하고 rewriter가 고치는 명령과 그대로 두는 명령의 표 작성 |
| 2주 | loader.c, docs/reference/threads.md·memory.md를 따라 스레드 슬롯·주소 공간·권한 변경의 수명 지도 작성 |
| 3주 | NVN record/replay와 셰이더 번역 체인을 읽고 CPU 완료와 GPU 완료가 다른 사례, reflection이 필요한 이유 설명 |
| 4주 | 진행 이벤트·합성 테스트·입력 해시를 묶어 “호환성 주장 하나에 어떤 증거가 필요한가” 검증 계획 작성. 실제 기기 성능은 별도 측정 과제로 분리 |
| 용어 | 이 프로젝트에서의 뜻 |
|---|---|
| AArch64 / ARM64 | Switch와 Apple 칩이 공유하는 64비트 ARM 명령어 계열. OS·호출 규약까지 같다는 뜻은 아님 |
| ABI | 레지스터·인자·스택·바이너리 배치 등 실행 코드끼리 지켜야 하는 계약 |
| NSO / NRO | Switch의 실행 모듈 형식. NRO는 실행 중 동적으로 로드하는 모듈에도 사용 |
| HLE / gate | 원래 시스템 서비스를 호스트 구현으로 대체하는 방식과 그 호출을 호스트로 넘기는 연결점 |
| TSD | pthread 스레드별 저장 공간. 게스트의 스레드 상태를 호스트에 보관하는 데 사용 |
| NVN / Metal | 각각 Switch와 Apple의 그래픽 API. 이 저장소는 전자의 명령을 후자로 재생 |
| SPIR-V / MSL | GPU 중간 표현과 Metal Shading Language. 오프라인 셰이더 변환 체인의 중간 단계 |
| IPA / build ID | iOS 앱 패키지 / 특정 실행 모듈 빌드를 식별하는 값. 앱 버전 이름과 패치 대상 코드를 구분 |
2026-10-27 개정 원본: 9bdef355 고정 소스 · 설정 우선순위와 비용 · Xenoblade Chronicles 3 검증 범위.
2026-10-28 현재 검토: docs/frontends.md · docs/launcher.schema.json · dm/games/settings.py · dm/mac/launcher.c · scripts/build_ipa_from_nsp.py. 아래 초판 링크와 이전 검토 블록은 각 날짜의 근거를 보존합니다.