대항해시대 2 (한글 DOS판) 내부 규칙·공식 문서
이 폴더는 KOEI 「대항해시대 2」 한글 DOS판의 MAIN.EXE를 디스어셈블해 정리한 게임 규칙 문서입니다.
편집기 기능은 없고 분석·문서만 담았습니다.
문서 목록
| 파일 | 내용 |
|---|---|
| trade.md | 교역품 시세: 매입·매각 가격, 세금과 면세증, 흥정, 거래에 따른 시세 변동, 월말 회복, NPC 상선의 영향, 투자→경제·공업, 지지도·동맹항, 보급품·조선소 가격 |
| navigation.md | 항해: 시간 단위, 바람·해류, 함대 속도, 식량·물 소비와 건강, 쥐·괴혈병, 폭풍·무풍·안개, 실종선, 해상 이벤트, 항구·마을 발견 |
| combat.md | 해전: 이동력·선회, 포격 사거리·피해, 부가 손상, 백병전, 결투 도전, 사기 붕괴, 컴퓨터 함선 AI, 도주·항복, 전리품 |
| npc.md | NPC 함대: 함대 구성, 국가 전략 모드, 목표 선택, 투자·교역 행동, 추적과 포기, NPC끼리의 전투, 해적, 함대 재생성, 라이벌 주인공 |
| character.md | 인물: 경험치·레벨업, 능력치 상승·하락, 고용, 급여·충성도, 나이, 명성 3종 |
| misc.md | 기타: 은행 이자·대출, 주점 선원 모집, 교회, 조선소(재질·내구·건조 기간·가격), 도구점, 건물 방문 시간, 난수 생성기, 월말 처리 순서 |
| scenario.md | 시나리오 바이트코드(SNR*.DAT)와 해석기, 명령어 표, 작위 이름·승급 조건, 길드 의뢰, 왕명, 주인공 여섯 명의 명성 조건·사건·엔딩, EVENT*.DAT |
| items.md | 도구 표, "사용" 분기, 측량기, 망원경·고양이·회중시계, 소모품, 보물 숨기기와 보물 지도 |
| landing.md | 상륙할 수 있는 땅, 물 찾기, 수리, 마을 탐색·환대·약탈, 선원 손실, 발견물 기록 |
| relations.md | 국가 기록·주인공 우호도 저장 위치, 처음 관계표, 월간 관계 변화표, 해전 승리 뒤 우호도, 추방·작위 박탈 |
| church.md | 교회·모스크: 기도와 기부의 운 공식(기부 문턱 1/11), 메시지, 운이 쓰이는 곳과 줄어드는 곳, 영문 공략 "10%" 설과의 차이 |
| data-formats.md | 게임 파일 전부의 내용과 형식: LS11 묶음, DATA1.LZW 엔트리, 그림 파일, 세이브 KOUKAI2.DAT 칸 배치, 항해사 기록, 표 파일 |
신뢰도 표시
모든 규칙 옆에 다음 중 하나를 붙였습니다.
- 확인됨: 한글판
MAIN.EXE의 코드로 확인했습니다. 두 가지로 나눕니다.- 확인됨[직접]: 공식과 상수를 한글판 디스어셈블에서 직접 읽었습니다.
- 확인됨[대조]: 영문판 연구(아래 참고 자료)가 분석한 루틴을 한글판에서 찾아, 명령어 구조와 즉시값 상수가
일치함을 기계적으로 대조했습니다(차이는 구조체 필드 위치, 메시지 출력 방식뿐). 공식의 의미 해석은 연구 자료를 따릅니다.
- 추정: 코드 일부나 정황으로 추론한 내용입니다. 사실로 단정하지 않습니다.
- 외부자료: 외부 연구·공략에만 근거하고 한글판 코드로 아직 확인하지 않은 내용입니다.
주소 표기
KO 0x293C9= 한글판dos/MAIN.EXE의 파일 오프셋.EN 0x2A0B7= 영문판MAIN.EXE(참고 연구가 쓰는 파일)의 파일 오프셋.DS:0x123A= 데이터 세그먼트 오프셋. 한글판 데이터 세그먼트는0x378B이고MAIN.EXE파일 오프셋 =0x3CCB0 + DS오프셋.- 한글판 MZ 헤더는
0x5400바이트, 코드 세그먼트는0x0000,0x0FB8,0x1F74,0x2DA1(영문판은 헤더0x5600, 세그먼트0x0000,0x0FC4,0x1E5F,0x2DFF, DS0x3657). - 세이브 슬롯 오프셋: 실행 중 세이브 한 칸은
DS:0x0C30부터 놓입니다. 그래서세이브 슬롯 오프셋 = DS오프셋 − 0xC30=DATA1.LZW15번 엔트리 오프셋 =MAIN.EXE파일0x3D8E0 + 오프셋. (확인됨[직접]: 15번 엔트리 32,573바이트가MAIN.EXE0x3D8E0에 그대로 있음)
영문판은DS:0x0E28이 슬롯 시작이므로, 영문 연구의DS:x는 한글판DS:x − 0x1F8에 대응하는 경우가 많습니다(구조체 크기가 바뀐 구간 뒤에서는 어긋남).
한글판과 영문판의 차이 (확인됨[직접])
한글판은 같은 소스를 다시 컴파일한 것으로 보입니다. 공식 상수는 지금까지 대조한 모든 루틴에서 같았습니다. 달라진 것은 구조체입니다.
| 항목 | 영문판 | 한글판 |
|---|---|---|
| 항해사(인물) 기록 | 42바이트 | 50바이트(이름·성 13바이트씩) |
| 능력치 8개(통솔력·항해술·지식·직감·용기·검술·매력·운) | +0x14..+0x1B | +0x1C..+0x23 |
| 항해 레벨 / 전투 레벨 | +0x1C / +0x1D | +0x24 / +0x25 |
| 항해 경험 / 전투 경험 (u16) | +0x1E / +0x20 | +0x26 / +0x28 |
| 나이, 충성도, 함대, 항구, 직책, 성격, 기술, 국적 | +0x22.. | +0x2A, +0x2B, +0x2C, +0x2D, +0x2E, +0x2F, +0x30, +0x31 |
| 선박 인스턴스 기록의 일부 필드 | +0x11, +0x12 … | 1바이트씩 뒤(+0x12, +0x13 …) |
| 선박 인스턴스 기록 크기 | 24바이트 | 25바이트 |
| 도구 기록 | 22바이트(성능 +0x14, 분류 +0x15) | 26바이트(성능 +0x18, 분류 +0x19) |
| 수집가·지도 제작자 기록 | 24바이트 | 21바이트 |
| 함대 기록 | 0x85바이트(슬롯 0x1DE0) | 0x85바이트(슬롯 0x2182) |
| 세이브 한 칸 | 0x7CC8바이트 | 0x823C바이트(파일 333,551 = 0x97 + 10 × 0x823C) |
| 인물 이름 | João Franco, Otto Baynes, Ernst von Bohr, Ali Vezas … | 조안 페레로, 옷토 스피노라, 에르네스트 로페스, 알 베자스 … |
시나리오 명령 D9 | 있음 | 없음(처리기도 바이트코드도 없음) |
자주 쓰는 한글판 데이터 위치 (확인됨[직접], 코드에서 읽는 주소)
| 내용 | 위치 |
|---|---|
| 소지금 (u32) | DS:0x123A (슬롯 0x60A) |
| 항해사 표 120명 × 50바이트 | DS:0x1242 (슬롯 0x612) |
| 도구 소지품 20칸 | DS:0x2D93 |
| 물·식량 배급률(%) | DS:0x2D55(물), DS:0x2D56(식량) |
| 이번 항해 일수(1바이트) | DS:0x2D54 |
| 이상기상·쥐·괴혈병 상태 바이트 | DS:0x0C3F (슬롯 0x0F; 쥐 0x10, 괴혈병 0x20) |
| 상륙 중 플래그 | DS:0x0F91 비트 0x18 |
| 해상 이벤트 10개 위치·종류 | DS:0x0F9E, DS:0x0FC6 (슬롯 0x36E, 0x396) |
| 바람-돛 효율 표 8×8 | DS:0x0714 (파일 0x3D3C4) |
| 교역품 분류 경계 10개 | DS:0x07C0 (6,10,17,21,26,31,33,36,40,46) |
| 대포 종류별 사거리 / 위력 | DS:0x0828 / DS:0x0838 (u16 × 8) |
| 난수 상태(u32, BSS·저장 안 됨) | DS:0xC138 |
| 국가 기록 7 × 32바이트 | DS:0x1106 (슬롯 0x4D6) |
| 주인공 명성·우호도·작위 6 × 14바이트 | DS:0x11E6 (슬롯 0x5B6) |
| 함대 70 × 0x85바이트 | DS:0x2DB2 (슬롯 0x2182) |
| 발견물 98 × 7바이트 | DS:0x7E88 (슬롯 0x7258) |
| 도구 100 × 26바이트 | DS:0x8144 (슬롯 0x7514) |
| 출항 때 망원경·고양이 비트 | DS:0xC158 (0x80, 0x40) |
| 작위 문턱 표(점술가) | DS:0xB8AE (파일 0x4855E) |
| 국가 관계 월간 값 표 | DS:0xAC74 (파일 0x47924) |
| 현재 항구 메타 기록(+2부터) 포인터 | DS:0xC6E2 |
| 현재 항구의 시장 기록 포인터 | DS:0xC678 |
| 현재 항구 표시 기록 포인터 | DS:0xC152 |
| 주인공 인물 기록 포인터 | DS:0xC67A, 주인공 번호 DS:0x1241 |
| 항구 표시 기록 130 × 20바이트 | 슬롯 0x5322 |
| 항구 메타 기록 100 × 37바이트 | 슬롯 0x5D4A |
| 시장 기록 13 × 128바이트 | 슬롯 0x6BC0 |
방법
- MZ 헤더와 재배치 표로 세그먼트를 나눴습니다. 오버레이는 없습니다.
- capstone으로 16비트 코드를 선형 디스어셈블하고, 즉시값과 주소를 지운 "명령어 모양" 열로 바꿨습니다.
- 영문판 연구가 인용한 루틴 주소를 같은 방식으로 바꿔, 한글판에서 유일하게 일치하는 위치를 찾았습니다(10개 명령어 n-gram 앵커).
- 대응 루틴을 나란히 비교하고 즉시값 상수 차이를 뽑았습니다. 핵심 공식은 한글판 코드를 직접 읽었습니다.
작업 스크립트와 결과는docs/.work/(uw.py, cmp.py, side.py, verify.py, amap.py, verify_out.txt)에 있습니다.
게임 실행(dosbox)으로 검증하지는 않았습니다.
참고 자료
- JohanLi, uncharted-waters-2-research (GitHub, 영문 DOS판 분석). 이 문서의 많은 규칙은 이 연구를 실마리로 삼아 한글판 코드로 확인했습니다. 원문은
docs/.work/ref/에 복제해 두었습니다.
통계와 남은 과제
통계는 아래 "집계" 절에, 확인하지 못한 것은 각 문서 끝 "확인하지 못한 것" 절에 있습니다.
집계
문서 본문에 붙은 신뢰도 표시의 개수입니다(본문에서 확인됨[직접], 확인됨[대조], 외부자료, 추정이라는 낱말을 센 값). 한 표시가 여러 규칙을 묶는 경우가 있어 규칙 수와 정확히 같지는 않습니다. 이 index.md의 범례는 세지 않았습니다.
| 문서 | 확인됨[직접] | 확인됨[대조] | 외부자료 | 추정 |
|---|---|---|---|---|
| trade.md | 16 | 4 | 7 | 3 |
| navigation.md | 6 | 12 | 16 | 0 |
| combat.md | 4 | 8 | 7 | 0 |
| npc.md | 1 | 10 | 7 | 1 |
| character.md | 2 | 6 | 6 | 0 |
| misc.md | 5 | 6 | 10 | 1 |
| scenario.md | 16 | 13 | 1 | 0 |
| items.md | 9 | 8 | 1 | 0 |
| landing.md | 6 | 7 | 0 | 0 |
| relations.md | 6 | 7 | 1 | 0 |
| church.md | 36 | 5 | 0 | 0 |
| data-formats.md | 29 | 17 | 1 | 6 |
| 합계 | 136 | 103 | 57 | 11 |
루틴 단위로 보면 영문판 연구가 인용한 루틴 130여 개를 한글판에서 찾았고, 그중 대부분이 명령어 차이 0, 상수 차이 없음(구조체 오프셋·메시지 출력 차이만)이었습니다. 시나리오 바이트코드 7개 파일은 영문판과 논리 명령 단위로 전부 비교했습니다(scenario.md 10절).
크게 남은 과제
- 게임 실행(dosbox)으로 공식을 검증하지 않았습니다.
- 영문판 연구에만 근거한 규칙(외부자료)이 아직 남아 있습니다. 주로 항해(망보기 거리, 해상 이벤트 종류), 해전(상선 항복 문턱, 해적 명성), 주점 세부입니다.
- 왕명 종류를 고르는 날짜 의존 분기, 시나리오 명령
FC, 기록 그룹 0F의 뜻. - 세이브 머리 15바이트와 칸 뒤쪽 767바이트 실행 중 상태,
DATA1.LZW6·7·8·12·13번 엔트리. - 우호도·명성의 게임 시작 때 초기화, 국가가 노릴 나라를 고르는 월간 공식.
- NPC 추적 포기 세부 분기.