KOEI

반각 가타카나를 전각 히라가나로 강제변환시키는 게임은 어떻게 한글 출력을 하는가.

K66Google 2018. 8. 29. 20:42

지난번의 이 게시물에서, 나는 윈도우10에서의 실행을 위해 일판 삼국지4PK와 삼국지5PK에 한글을 출력시키려고 시도했으나 LS11 압축방식을 사용하는 메시지 파일이 한글을 제대로 출력하지 못한다고 서술하였다.

따라서 반쯤 포기한 상태로 방치해두고 있었는데, 웹서핑 도중 어느 다음 카페의 게시물을 보게 되었다.


(출처: http://cafe.daum.net/Europa/2M1/955 )


그것은 코에이가 제작한 '제독의 결단4PK'의 한글화 정보 게시물이었다.

여기서 나는, '반각 가타카나를 전각 히라가나로 변환하지 않음' 이라는 문장이 눈에 들어왔다. CreateFontA나 반각 필터링은 이미 널리 알려져있지만 전각 히라가나 강제변환과 관련된 자료는 그동안 찾아볼 수가 없었기 때문이다.


아래로 스크롤을 내리니 메시지 파일과 관련된 설명이 나오는데, 제독의 결단4PK도 메시지 파일에 반각 가타카나를 사용한다는 점을 알 수 있었다.

그렇다. 삼국지4PK · 5PK 일판과 메시지 구조가 똑같다. 게다가 신장의 야망 시리즈로 가면 열풍전, 람세기 등의 메시지 구조와도 동일해진다. 실제 한글화를 하기에는 글자수 제한 등으로 어렵겠지만 기술적으로 한글 출력은 가능하다는 이야기이다.


일단, 제독의 결단4PK 실행파일을 분석해보기로 하였다.


실행파일을 Ollydbg로 열어서 보기로 하였다. 첫번째로 CreateFontA의 한글 로케일 변경이다.

삼국지4, 삼국지5는 그냥 PUSH 80을 PUSH 81로 수정하면 됐는데 여기선 MOV 함수 (왼쪽 값에다 오른쪽 값을 대입하라는 함수인듯) 로 넣고 있다.

맨 처음에 EAX6391F4라는 주소값이 들어갔다. 이 값을 기억해두고 Charset이라고 적힌 곳으로 가자.

Charset 한 줄 위를 보니 다시 EAX+1C 라는 걸 ECX에다 대입하려 하고 있다. 아마 이 구문이 인코딩과 관련되었을 것이다.

(아랫 줄 PUSH EDX에 현혹되면 안된다. 이건 Charset 값이 아니라 OutputPrecision 값과 관련있는거다. Charset과 관련 있는 건 ECX다.)

EAX가 처음에 6391F4라는 값이 들어갔으니 6391F4 + 1C = 639210 아닌가? 생각했는데... 1C를 더하는게 아니라 빼야 계산이 맞아떨어지게 된다. 왜 그런지는 나도 모른다. 따라서 6391F4 - 1C = 6391D8 이며, 아래 헥스 덤프 창에 6391D8 자리로 가니 81이 있다. 이 값이 바로 한글 로케일로 바꿔주는 것이 되겠다.



두번째로 반각 · 전각 필터링이다. 평범하게 9F → 0C8 로 바꿔놓았다. 삼국지4 · 삼국지5를 비롯한 반각 필터링이 있는 대부분의 일본어 게임들은 거의 같은 방법을 쓰는 모양이다.

ADD EAX, 0E1을 161 등으로 바꾸는 방법은 해당 게시물에서 언급하지 않아서 굳이 찾아보지 않았다.



세번째, 여기가 가장 중요한 반각 가타카나의 전각 히라가나 강제변환 구문이다.

이 실행파일은 한글 출력을 위해 CMP EAX, 0A6 을 지나서 JMP로 무조건 점프하고 있다.

자, 여기서 왜 0A6이 튀어나왔는지 생각해보자.


일단 맨 앞의 0은 어떤 16진수가 A~F로 시작할때 붙이는 것이다. (0~9로 시작하면 그대로 쓴다.)

A6은 반각 가타카나의 ヲ 자이며, 여기서부터 DF (반탁점, °) 까지 반각 가타카나 코드값이다. A1부터 A5까지는 일본어 문장부호라서 변환하지 않는 것으로 보인다. (이 블로그에서 반각 가타카나에 대해 간략히 다룬 게시물이 있는데, 그걸 보려면 여기 클릭)


즉, 원래는 실행파일이 하나씩 바이트를 읽다가 A6 미만인지 아닌지 (JL 점프문) 확인한 뒤에 A6 미만(A5... A4... A3...)일시 점프시키고 A6과 같거나 그 이상(A6.. A7.. A8...) 이라면 점프안시키고 강제로 히라가나로 변환하는 것이다.


한글이 쪽쭈혻쯤같이 괴문자로 출력되는 현상도 바로 여기에 있었다.

'한글'의 코드 값은 C7 D1 B1 DB인데 4개 바이트 모두 A6을 초과하고 있다. 따라서 전각 히라가나 강제 변환 구문으로 들어가게 되어서 괴문자가 나오게 된 것이다.


이걸 JMP로 바꿔서 A6 미만이든 초과든 모두 점프시켜야 메시지 파일 내 한글도 강제변환에 휘말리지 않고 그대로 출력되게 된다.



그렇다면 다른 게임에서도 이 방법이 통하는지 보자.  테스트할 게임으로 신장의 야망 9PK 람세기를 골랐다.

람세기도 LS11 압축 메시지 형태를 사용하고, 메시지내에는 반각 가타카나가 존재하며, 실행파일에서 전각 히라가나로 강제변환되는 구조를 가지고 있다.

한글 코드(81)와 반각 필터링까지 고쳐놓은 실행파일로 미리 수정해놓았던 한글로 된 메시지를 출력하니, 역시나 전각 히라가나의 뷁어 버전으로 출력되서 나왔다.



이제 실행파일을 열고 CMP ECX, 0A6 을 검색한다. (EAX로 검색해서 없으면 EBX, ECX, EDX, AL, BL, CL, DL 이렇게 바꿔가면서 검색하면 된다.)

보니까, CMP 밑에 바로 JL이 와 있다. 제독의 결단 4PK 실행파일에서 본 것과 흡사하다. 

저 JL을 JMP로 고치고 다시 실행해보면 어떻게 될까?



성공!

이로써 이 방법은 코에이의 다른 게임에서도 먹힌다는 것이 증명되었다.

그렇다면 삼국지4PK와 5PK 일판도 이 방법이 먹힌다는 거겠지?



삼국지4PK 일판은 CMP EAX, 0A6 을 검색하고 JL을 JMP로, 

CMP EDX, 0A6 을 검색해서 JNZ를 JMP로, 뒤의 주소는 적절하게 교체하였다.



삼국지5PK 일판 (일본 천상기 사이트 버전) 은 CMP BL, 0A6을 검색하고 JB를 JMP로,

CMP CL, 0A6을 검색하고 JB를 JMP로 바꿔주었다.

여기는 EAX, EBX... 같은 X자돌림이 아닌 BL, CL...같은 L자돌림인데 그 이유는


EAX가 총 4바이트(32비트)로 구성되어 있는데 맨 끝의 1바이트가 AL 이라고 불러서 그렇다.

EBX면 BL, ECX면 CL... 이런 식이다.


자, 이제 LS11 메시지를 수정하고 결과를 보자!




아주 좋다. 글자가 짤리기는 하지만 그건 내 알바 아니다. 한글만 제대로 출력되면 되는 것이다.

보름 동안 머리 싸매다가 포기했던 문제가 확 풀리니까 매우 뿌듯하다.


혹시 나와 같은 문제로 인해 고생하고 있었다면 이 글을 많이 참고해주었으면 좋겠다.

그럼 이만...