케로로

GBA 케로로 중사 격주 케론프리 대작전에 한글을 출력시키고 말겠다. (1부)

K66Google 2020. 10. 5. 20:00

케로로 중사 격주! 케론프리 대작전 입니다!! 라는 GBA게임이 있다. 국내에서는 본명보다 '케로로 레이싱 게임' 으로 더 잘 알려져있다. (온라인게임 케로로 레이싱과는 관계없다.)


국내에도 쥬얼게임으로 발매가 되기는 했다. 그러나 한글화는 안 되어있는 모양이다. (되었으면 분명 소문이 돌았겠지)

아무튼 롬파일을 Crystaltile2로 분석을 진행해보았다.


첫 대사 파트가 있는 부분은 000C6B9C이다. (ケロロ「プッフィ~ッようやく...)

이곳의 대사 일부를 亜滌漾熙 纊黑 라고 바꿔보았다. 굳이 옆의 한자들을 선택한 이유는, 이 게임이 Shift-JIS 한자영역을 지원하는지 안 하는지를 알아보기 위해서다.

Shift-JIS의 한자영역은 크게 889F~9FFC / E040~EAA4 / FA5C~FC4B 세 개의 구역으로 나눠지는데, 亜滌는 889F~9FFC 에 속하고 漾熙는 E040~EAA4에 속하며, 纊黑은 FA5C~FC4B에 속한다. 그 중에서 889F~9FFC의 한자영역만 지원해도 한글 2350자를 덮어씌워서 한글화를 시도할 수 있다.

다행히 이 게임은 해당 한자영역을 지원한다. (그러나 ASCII 같은 1바이트 문자는 지원하지 않는다.) 

이제 폰트만 찾으면 된다. 그러나...


폰트를 찾는것 부터가 큰 난관이었다. 아니, 폰트는 어떻게든 찾았다.


1FF30F / GBA 4bpp / 8x31 / 팔레트 조합의 마지막 색깔줄


이렇게 하면 폰트가 얼핏 보인다. 이것도 알파벳과 숫자를 보고 겨우 찾아낸 것이다. 눈썰미가 좋지 못했다면 평생 못찾을 뻔했다.

더 큰 문제는... 폰트를 어떻게 수정하냐는 것이다.


보다시피 Crystaltile2로 그냥 도트 찍어서 만들면 이렇게 깨진 폰트가 출력된다. 도트 찍기로 만들기는 무리라서, 폰트의 헥스 구조를 분석해야 했다.


폰트는 한 글자당 62바이트로 구성되어 있었다. 10 04 라는 폰트 시작을 알리는 2바이트가 있고, 그 뒤로 60바이트의 데이터가 있다.


또한 한 글자당 8x15의 픽셀을 가지고 있으며, 2바이트가 가로 4타일씩 관리한다.

그리고 홀수타일, 짝수타일의 글자·배경 판정 기준이 다르다.


크리스탈타일 조합 마지막 줄 기준으로 색깔값은

홀수타일 - 글자(119) / 배경(017)

짝수타일 - 글자(204 또는 221 [짝수타일에서 획을 긋기 시작할때]) / 배경 (119)



폰트 판정 기준에 맞게 도트를 그어줬더니 게임 상에 한글이 잘 보이고 있다.

그러나 이태리 장인 마냥 한땀한땀 도트를 찍고 있을 수는 없는 노릇이다.

그래서 도트를 찍으면 그걸 헥스 코드로 변환시켜서 롬파일의 해당 폰트 영역 주소에 덮어씌워주는 프로그램을 제작하기로 하였다.

그럴려면 먼저 4타일의 헥스값 경우의 수를 파악해두어야 한다. 무슨 말이냐면...


(o는 글자 픽셀, x는 배경 픽셀)


xxxx - 71 71

oxxx - 77 71

ooxx - C7 71

ooox - C7 77

oooo - C7 C7


xoxx - D1 71

xoox - D1 77

xooo - D1 C7


xxox - 71 77

xxoo - 71 C7


xxxo - 71 D1


oxox - 77 77

oxxo - 77 D1

xoxo - D1 D1


ooxo - C7 D1

oxoo - 77 C7


이런 식으로 4타일 중에 어디가 글자 타일이고 배경 타일인지에 따라 변환되는 헥스값이 달라지므로 미리 경우의 수를 파악해 놓아야 한다는 뜻이다.


폰트 영역 주소는 폰트가 하나당 62바이트를 차지한다는 점을 감안하여, 엑셀의 자동채우기 기능을 써서 글자 2350개의 영역 주소를 단번에 알아낼 수 있다.

알아낸 주소들은 txt 파일로 저장한다.



그리고 프로그램을 시작할때 저장한 폰트 영역 주소 txt 파일을 자동으로 로드하게 한다. 그런 다음 글자 도트를 찍고 헥스 코드로 변환시킨 다음, 롬파일에 덮어쓴다.

덮어쓰고 난 뒤 Crystaltile2로 시작 부분의 대사 주소로 가서 889F(亜)를 넣어보았다. 그러니 '가' 자로 치환되서 잘 출력된다.


그런데...



 

 

캐릭터 설정의 필살기 탭 폰트와 레이싱 도중에 나오는 대사는 '가' 로 치환되지 않고 그대로 亜로 나온다.

이 게임은 폰트를 한 세트가 아닌 두 세트를 사용하고 있었던 모양이다.

하나도 찾기 힘들었는데... 또 하나를 더 찾아야 한다고..? 지금까지 한글화 시도가 되지 못한 이유가 있었다.


이게 폰트처럼 보이는가?

아마 대부분의 사람들은 그냥 무시하고 지나칠 것이다.



그런데 이게 폰트가 맞았다. 

다행히 내가 처음 발견한 폰트 영역에서 위로 조금만 가니까 있었다. 멀리 있었으면 또 한참 헤맬뻔했다.


1B2B18 / GBA 4bpp / 8x31 / 팔레트 조합의 마지막 색깔줄


두번째 폰트는 한 글자당 38바이트로 구성되어있으며, 폰트 시작을 알리는 헥스는 0C 03 (2바이트) 이다. 그 뒤로 36바이트의 데이터가 있다.

데이터 구조는 앞에서 분석한 폰트 영역과 똑같아서 헥스값 경우의 수를 또 파악할 필요는 없었다.

아무튼, 지금 이 화면으로는 이게 무슨 글자인지 도저히 식별이 불가능하다. 亜자가 어디있는지도 찾기 힘들다. 그래서...


엑셀로 자동 채우기를 해가면서  첫번째 폰트 영역의 주소와 대조를 해보았다.

같은 폰트 구조라면 글자 순서도 똑같을 것 아닌가?


대조한 결과는 1B82F8이었다. 이곳의 일부 영역을 71 71로 바꾸었다.


그러나 亜자는 그대로였다. 

아무래도 번지수를 잘못 짚은게 틀림없다. 이제 어떻게 해야 하나?


...라고 낙담하고 있을때, 중간에 유난히 속이 텅 빈 것 같은 글자가 하나 보였다. 바로 한 일(一) 자 였다.

一자는 88EA이므로 889F(亜)와도 가까운 자리다. 마침 오른쪽 옆옆칸에 토란 우(芋), 옆옆옆칸에 도장 인(印) 자와 비슷하게 생긴 자형도 보이니까 一자가 틀림없다.

그럼 一자의 위치 주소를 알아내서 첫번째 폰트 영역의 一자 주소와 대조해보면 어떨까?


위치 주소는 1B8ED8이었고, 첫번째 폰트 영역의 一자 주소는 209496이었다.

두번째 폰트 영역이 첫번째 폰트 영역보다 5글자가 밀리는 점을 확인할 수 있었다.


그렇게 해서 다시 알아낸 亜자의 두번째 폰트 영역 주소는 1B83B6이었다.

이곳의 일부 데이터를 71 71로 수정해보자... 亜자가 변한 걸 확인할 수 있다. 성공이다.


두번째 폰트는 6x12 픽셀이었다. 그러나 2바이트가 4타일씩 취급하는 것은 첫번째 폰트와 동일했다. 그런데 한 줄에 6픽셀인데 어떤 방식으로 취급을 한다는 것일까?


분석한 결과 줄 같은 거 무시하고 무조건 2바이트=4타일이었다. 무슨 말이나면...


112

233

445

566

778

899

001

122

334

455

667

788


이렇다는 것이다. 

위의 내용 중 2, 5, 8에 주목하기 바란다. 줄이 한 칸 밀려나도 앞바이트의 영향을 받고 있다.


굉장히 머리가 복잡해지니까.. 그냥 프로그램에다 6x12 픽셀도 도트 찍기가 가능하게끔 수정하자.

또한 두번째 폰트 영역 주소가 첫번째 폰트 영역 주소와 연동되도록 txt파일 구조도 바꿨다.


그렇게 해서 나온 결과는...? '가' 자가 캐릭터 필살기 창에 잘 출력되고 있다.



레이싱 도중 캐릭터 대화창에도 '가' 자가 잘 출력되고 있으니 성공이다.


그럼 2350자의 폰트 도트를 찍는 일만 남은건가?


……


……


이걸 어느 세월에 다 찍어!!!


아무래도 수동으로 도트 찍기는 그만두고 자동으로 폰트를 찍어낼 방법을 고안해야겠다.



- 2부에서 계속 -