황짜장 맵핑
문서 없는 메모리에서 안 가 본 층의 계단을 찾는다
디아블로 2 레저렉션 오프라인 싱글 플레이 화면 위에 벽 · 출구 · 이동진 · 몬스터 · 경로를 겹쳐 그리는 데스크톱 오버레이. 공개된 구조 문서가 없는 최신 버전의 메모리 구조를 직접 조사해 오프셋 표를 만들고, 그 위에 지도 · 경로 · 알림을 올렸다. 게임 메모리는 읽기만 한다 — 주입 · 후킹 · 쓰기는 하지 않는다.
문서 없는 게임 메모리를 역분석해 만든 실시간 지도 오버레이 — 오프라인 싱글 전용
- 기간
- 2026년 9월 ~ 10월
- 역할
- 전체 — 메모리 구조 역분석 · 지도 · 경로 · 렌더링 · 설정 UI · 테스트
- 분류
- 소프트웨어, 데이터
- 등급
- 주요 작업 — 구조와 판단이 남아 있는 것
화면 캡처가 아직 없어, 아래에 구조와 판단으로 적었습니다.
무슨 문제였나
기존 공개 자료는 예전 버전 기준이라 현재 버전에서는 구조체 위치가 맞지 않았다. 게다가 아직 가 보지 않은 구역은 메모리에 출구 좌표 자체가 없어서, 단순히 값을 읽는 것만으로는 «다음 층 계단이 어디 있는지»를 알 수 없었다.
어떻게 풀었나
패턴 스캔으로 유닛 테이블을 찾고 방 · 레벨 · 막 구조체를 하나씩 따라가며 오프셋을 검증했다. 결정적인 단서는 방마다 붙어 있는 «맵 조각» 레코드였다 — 가 보지 않은 방에도 존재하고, 조각 이름에 계단 · 입구 · 웨이포인트 같은 의미와 통로 방향이 들어 있었다. 조각을 방향으로 이어 그래프를 만들고 입구에서 계단까지 경로를 계산해, 실제로 그 자리에 계단이 있는지 게임 안에서 확인했다.
구조
- 01메모리 계층 — 모듈 패턴 스캔 → 유닛 테이블 · 방 · 레벨 구조체 리더 (읽기 전용)
- 02안전 게이트 — 온라인 접속이면 오버레이가 켜지지 않는다 (오프라인 확인을 통과해야 실행)
- 03지도 계층 — 지나간 방의 지형 + 맵 조각 기반 예측 지형 + 출구 분류
- 04경로 계층 — 조각 인접 그래프 · 충돌 지도 위 경로 탐색
- 05표시 계층 — 게임 바닥에 겹치는 지도 / 개요 창 / 하단 정보 바, 무거운 작업은 뒤 스레드
- 06게임 데이터 표 — 몬스터 · 아이템 · 룬워드 · 지역 이름 (한글은 실행 중 게임에서 직접 추출)
어려웠던 것
- 구조 문서가 없는 버전 — 알려진 구버전 값과 비교하며 오프셋마다 게임 화면으로 검증하는 표를 따로 남겼다
- 안 가 본 구역은 출구 좌표가 메모리에 없다 — 방마다 붙은 맵 조각 이름과 통로 방향으로 연결 그래프를 만들어 계단 위치를 추정, 실제 위치와 일치함을 확인
- 공개 한글 표는 옛 번역이라 현재 게임 표기와 달랐다 — 실행 중 게임의 문자열 해시맵에서 1만여 개를 직접 추출해 이름 표를 다시 만들었다
- 순간이동할 때 화면이 튀는 문제 — 프로파일링해 보니 하단 바가 다시 그려질 때마다 90ms 걸리는 시스템 조회가 원인. 결과를 캐시해 50ms 넘는 멈춤을 분당 173회에서 10회로 줄였다
무엇을 만들었나
- 게임 바닥 위에 벽 · 출구 · 이동진을 직접 겹쳐 그리기 (지나간 방은 진하게, 예측한 방은 흐리게)
- 가 보지 않은 층의 계단 · 입구 위치 예측과 경로 안내
- 몬스터 등급 · 면역 표시, 소환수 · 용병 상태
- 귀한 아이템 드롭 알림
- 공포의 영역 현재 지역 · 남은 시간 표시, 원하는 사냥터면 강조 · 소리
- 처치 수 · 시계 · 버프 · FPS 하단 바
- 룬워드 검색 · 장비 추천 창
- 게임 모드(Mod) 의 이름 표와 자동 동기화
- 설정 창 · 단축키 재지정 · 지도 모드 전환 (바닥 → 개요 창 → 끔)
쓴 기술
무엇이 남았나
- 현재 버전 기준 메모리 구조 오프셋 표 작성 · 게임 안에서 검증
- 자동 테스트 338개 중 335개 통과 (9월 기준 — 실패 3개는 봇 쪽 변경 영향)
- 10월 2일 — 안 가 본 방의 예측 지도가 안 그려지던 문제를 고쳐 다시 표시
- 개인 오프라인 플레이용 — 배포하지 않았습니다
알게 된 것
문서가 없을 때 필요한 건 추측이 아니라 검증 절차다. 값 하나를 찾을 때마다 «게임 화면에서 무엇으로 확인했는지»를 같이 적어두니, 버전이 바뀌어도 어디서부터 다시 보면 되는지 바로 알 수 있었다. 그리고 경계(오프라인 전용 · 읽기 전용)는 약속이 아니라 코드로 막아야 지켜진다.


