잘못된 정보가 있다면, 꼭 댓글로 알려주세요(비로그인 익명도 가능).
여러분의 피드백이 저와 방문자 모두를 올바른 정보로 인도할 수 있습니다.
감사합니다. -현록
현록의 기록저장소
섀도 오버 미스타라 한글화 후기 본문
근래 몇일간 블로그를 방문했던 분들이라면
한글화 작업 중에 중단을 하거나 여러 실패 경험을 적어둔 글을 보셨을 수도 있다.
(결국 릴리즈 했으니 다 내렸지만)
첫 시작은 이랬다.
좀 어린 손님에게 게임을 시켜주면서,
라이덴2라든지 스노우 브라더스2라든지 어린 나이에도 쉽게 할 수 있는 게임을 틀어줬었는데,
문득, 던전즈 앤 드래곤즈 아케이드 게임이 생각났다.
그래서 찾아봤는데, 한글롬이 전혀 없었다.
꽤 명작인데, 그 오랜 시간동안 한글화가 안되었다?? 아무도 건드리지 않았다??
(이건 하면서 알게된건데, 몇 년 전 시도해 본 사람이 보이긴 했었다. 경과는 모르지만)
생각해 본 상황은 이렇다.
1. 아케이드 게임 특성상 메모리가 아주 빠듯하다.
2. 유니코드 지원은 당연히 안될테고, 한글을 어딘가 때려박아서 불러오는 방식을 써야할 것이다.
3. 근데, 새로운 폰트를 넣는 것도 어렵고
4. 조합형을 구현할 수 없을 것 같고, 완성형을 넣는대도, 문장들을 올바른 문장으로 할 용량이 될까?
5. 문제는, 이 어려운 것들을 다 해낼 수 있어도, 게임의 플레이 타임이 짧다.
(아케이드 게임치고 긴 것이지, 포켓몬 시리즈에 비하면 택도 없지않나.)
6. 이 모든 고생을 한 것에 비해 좀 허무할 수 있는 작업이다.
(고생 중에 결과를 생각하면 중도 포기하게 만들 수 있다.)
7. 번역은 되어있으면 좋지만, 무시해도 게임에 큰 지장은 없다.(언어장벽이 크지 않다.)
(이것 역시 고생 중에 에라이 하고 포기하게 만들 수 있다.)
이 모든 이유를 불문하고, 누군가는 팬심에 짬내어 하셨을 수도 있다.
그런데 결과물이 전혀 없다니..
우선, 롬을 수정하는 것을 생각하지 않았다.
한글화 좀 한다는 분들도 해내지 못한 것이기도 하고, 나도 경험이 없다.
유저는 거추장스러운 동작을 하지 않아도 되면서, 별다른 위화감없이 한글을 볼 수 있는 방법들을 생각해봤다.
먼저 이미지 서칭을 생각해봤다.
문제는, 약 296장의 글자 화면을 캡처하게 되었다.
(이건 대화, 푯말정도만 센 것이지, 나중에 추가한 장비관련 텍스트면 더 넘어갈 듯)
매번 이만큼의 이미지 비교를 하긴 힘들다.
1초내로 모두 비교하는 건 무리고, 순차적으로 진행할텐데, 그러면 너무 느리다.
그래서 멀티쓰레딩을 구현해봤다.
멀티쓰레드 세이프하지 않은 환경에서, 멀티쓰레드 세이프하게 하려고 꽤 고생했다.
뮤텍스를 직접 만들고 이리저리 디버깅하고..
1~296으로 갈 것을,
1~10, 11~20, 21~30, ...으로 동시에 비교할 수 있게 만들어봤다.
(20씩 가는 것도 느려서 유저가 딜레이를 느끼게한다.)
우선 루프 자체는 짧아지니 빠르게 캐치할 순 있겠지만,
이제 쓰레드가 많아지니까 버벅이기 시작한다.
쓰레드가 4개까지는 그럴만한데, 6개를 넘으면 아주 버벅인다.
이건 유저가 알아채지 않는 상황이 아니다.
GdiPlus가 리소스를 꽤 사용하는 작업이니, 여러 쓰레드가 이 짓을 벌이느라;;
게임에서 bitmap을 여러 장 동시에 만드는 것도 버벅여서
(아마 bitlock을 여러번 해대니 그 동안 멈추는 것으로 보이니까)
최대한 줄여보려고 bitmap은 한 개만 만들어서 넘겨주고,
뮤텍스로 모두 사용이 완료될 때까지 기다린 후에 파기하는 등 멀티쓰레드 세이프하게 짰지만,
서칭자체가 오래걸렸다.
그래서 이번엔 bitmap을 원본크기가 아닌, 아주 작은 축소판으로 만들어서 서칭속도를 개선하기로 했다.
원래는 원본에서, 추출해둔 이미지와의 비율을 구해서, 그 비율만큼 원본을 축소 후에 검사를 했지만,
아예 원본을 고정된 299x224로 줄여서 찍고, 이미지도 1440x1080이 아닌, 299x224로 다시 캡처를 했다.
즉, 296장을 다시 찍으려 다녔다는 소리다ㅡㅡ
원래 캡처해둔 것을 줄이면 되지 않냐고 할 수도 있지만,
포토샵으로 줄이는 것보다,
최대한 실 환경과 같도록 가야 서칭도 잘 될 것 같아서 GdiPlus가 줄여주는,
플레이 상황에서 다 건져냈다.
속도는 개선됐지만, 그래도 유저가 알아챌 수 있는 정도이고,
무엇보다 한 쓰레드에서 동시에 모두 비교할 순 없다.
여러 쓰레드는 여전히 버벅인다.
방식을 좀 바꿔볼까?
스테이지 4에 진입하면, 이전의 0~3 쓰레드는 종료된다거나.
근데, 불러오기 상황은 어떻게 고려할 것이지?
초기화 단축키를 둔다고 해도, 그럼 처음에는 결국 전체 쓰레드를 돌려야할 것 아닌가?
이러면서 무산.
결국 후킹밖에는 답이 없어보였다.
롬 해킹이 아니고서 런타임 중에 알아챌거면 당연히 후킹이 가장 적합한 방식 아니겠냐고 하면,
그렇긴 한데,
한글화를 하는 것이 목적이 아니었고,
뭐랄까, 이렇게 해보면 어떨까?하는 재미로 한 것이라서
하나의 방식에서 해볼만한 것을 다 해보고 싶었다.
이걸 경험으로 다음에 또 어떤 것을 만들게 되면 바로 떠올릴 수 있도록,
한계치는 겪어보고 싶었다고 해야하나...
여기서 에라이 접자고도 생각했다가,
(애초에 후킹이나 리버싱으로 텍스트의 유의미한 지표를 찾아내는 것까지 생각하지 않았다. 너무 본격적이 되어버리잖아..)
해둔 게 아쉬워서(296장 캡처 및 출력용 글자 리소스 만들어둔 것들..;;)
디버깅을 시작했다.
한글화를 해본 것은 아니지만, 대략의 상식은 있다.
텍스트를 표출할 때, 기존에 이미 만들어 둔 string인지 char배열이든지를 가리키는 포인터 형태로 사용할 것이라는 것.
즉, 다른 텍스트를 표출하는 상황들을 불러오면서 값을 비교했다.
특히, 전혀 다른 상황인데 같은 말을 하는 NPC쌍이 2쌍 정도 있어서 도움이 되었다.
(대화 부분만 값이 같고 나머진 다를 수 있으니까)
결국 유의미한 주소(char배열을 가리키는)를 찾았고,
이제 또 리소스 노가다가 시작되었다.
다시 296번의 상황을 돌면서 그 주소가 가리킬 값을 기록해두는 것.
여기서 툴을 하나 만들었다.
(뭐랄까, Horse개체를 만들기 위한 HorseFactory를 짓는 상황인가..)
해당 주소의 값을 클립보드로 가져오는 툴.
그리고 진행하면서, 플레이어가 정한 이름을 이용하는 구간이 있었는데,
이 경우는 미리 만들어둔 텍스트를 쓸 수 없을텐데, 어떻게 하고 있을까 보니,
특정한 char 배열을 가리키는 주소값을 공통적으로 쓰고있고,
그 char 배열을 즉석에서 조합하고 있었다.
문자는 Ascii코드보다 얼만큼 큰 숫자를 규칙적으로 사용하고 있었다.
이제 여기서 해당 char 배열의 첫 주소를 또 알아내야 했다.
Ascii보다 얼만큼 큰 규칙이라는 것은 후에나 알아낸 정보이지, 처음에 어떻게 알겠나.
그냥 또 즉석주소를 가리키는 상황을 여러개 찍어서 비교했다.
이게 줄 수로 가리키는게 다를지, 글자마다 다르게 할지도 모르는 상황에서 일일이 비교하면서,
글자마다 하나씩 써주고 있다는 것을 알았고,
결국 첫 글자의 주소를 구할 수 있었다.
이제는 툴에 기능도 추가했다.
해당 첫 글자의 주소로부터 바이트 단위로 읽으면서,
Ascii코드가 아닌, 내장 규칙으로부터 텍스트를 읽어오는 것.
이제 즉석생성 텍스트는 해당 주소를 가리킬 때, 문자열비교까지 함께하는 방식으로 클리어.
그리고 푯말을 읽었더니 푯말은 텍스트의 주소가 변함이 없었다.
또 다른 주소를 이용한 것.
그래서 또 여러 푯말을 읽으면서 유의미하게 달라지는 곳을 찾았고,
이 주소 역시 추가적으로 값을 기록했다.
푯말은 다 고정인 듯 했으나, 전설의 검과 홀리어벤져의 저주 해제 글은 또 즉석생성이었다.
다행인건 즉석생성 char배열 위치는 동일하게 사용하고 있어서, 크게 어렵지 않았다.
하는 김에 장비회득/깨짐도 하기로 해서, 역시 유의미하게 달라지는 주소를 찾아서 값들을 기록했다.
(이쯤되니 그냥 수월하게 찾아짐)
그리고 텍스트는 후반으로 가서 최종장부터는,
굳이 플레이어명에 따라 달라지는 것도 아닌데 즉석생성을 하고 있었다.
아마 저장해둘 텍스트의 용량이 부족해서 그런 듯 했다.
이제 게임 내 원하는 텍스트가 표출되는 상황을 구별할 수 있게 됐으니,
기존의 이미지 서칭에서 결과를 띄우던 것들을 다 교체했다.
그런데, 서칭에서는 서칭 결과의 x,y로부터 비율만큼 곱한 크기로 결과를 띄워줬었는데,
이건 텍스트의 자체로 할 것이라(이 때는 텍스트의 x,y 주소를 생각하지 않았다)
그냥 결과도 1440x1080짜리 투명한 배경에 원하는 위치에 텍스트를 둔 이미지들로 바꿨다.
텍스트 레이어 아래에 원문은 테두리가 4px정도로 입혀진 크기가 검은색 픽셀들로 구성하여 가리는 방식으로.
그러다가, x,y 위치도 조절할 수 있지 않나? 싶어서
x,y 주소를 찾아서 아예 화면 밖으로 밀어버리고,
그냥 검은 블록 없이 텍스트만 이미지에 존재해도 되었고,
푯말 역시 원문보다 위가 아니라, 원문 위치에 적어줄 수 있게 되었다.
굳이 이미지 파일을 고려한 것은,
글자들의 테두리나 여러 속성을 꾸민 상태로 저장하니까, 더 게임에 맞는 분위기로 준비해둘 수 있어서였다.
(그리고, 사용자가 직접 번역 결과를 수정할 수도 있다.)
근데 이것도 300장 정도 가니까 용량이 꽤 된다.
배보다 배꼽이 커짐ㅋㅋ
그래서 이미지 파일은 다 버리기로 하고,
GdiPlus 기반으로 글자를 생성하기로 했다.
(ㅡㅏㅏㅏㅏㅏ 그만해ㅐㅐㅐㅐㅐㅐㅐㅐㅐ)
썩 이쁘진 않지만..;;
x,y에서 값을 읽어서 해도 됐을테지만,
그 x,y에 어떤 걸 또 조합해서 사용하는 상황이 별개로 존재할 수도 있어서
이 텍스트의 위치는 그냥 직접 하기로 했다.
즉, 300개 이상의 상황을 줄마다 x,y 작업을 했단 것.
(1인 작업이니 결국 내가 다 한다.. 미쳐)
그리고 가장 귀찮았던 플레이어 명이나 아이템 명 스킬 명에 따라 달라지는 상황은,
내가 사랑하는 정규표현식으로 잘 캐치해서 적용시켜줬다.
그리고 결국 끝.
그런데, 처음에도 말했듯이,
난 굳이 이 게임의 매니아이기 보다는,
10여년간 왜 한글화는 안되었고, 이런 방식으로는 안될까싶은 호기심이나 오기같은 것이었어서
구동환경을 고려하진 않았는데,
유럽판보다는 아시아판을 더 많이 하는 것을 알게됐다.
그래서 아시아판을 구동해보니, 주소인지 값인지 달라서 인식이 안되었다.
뭐, 롬이 다르니 예상을 한 상황이었다.
처음에는 생각을 안 했다가, 자고 일어나서 그냥 아시아판도 순식간에 추가할 수 있지 않을까 싶었다.
원판에 대한 주소와 값들을 엑셀시트로 정리해뒀어서,
그냥 그 옆에 아시아판의 값들을 적어보기로 했다.
주소를 찾는 것도 경험이 있어서 빨리 찾아졌다.
값들은 2바이트 중, 뒤의 1바이트는 같고, 앞의 1바이트만 차이가 났다.
뒤는 인덱스이고, 앞은 어떤 배열이나 그런 세트겠지.
모두 같은 규칙은 아니었고, 앞의 1바이트가 세트마다 조금씩 달랐다.
그래서 결국 모든 상황을 거의 직접 돌게됐지만, 한 30분 내로 다 된 것 같았다.
약간의 분기 상황은 세트가 동일하다고 판단해서 그냥 근처의 규칙으로 비교하면 됐으니.
그리고 오히려 이 때는 즉석생성이 편했던게,
즉석생성 포인터 값만 한번 캐치해두면, 문자열비교는 같은 규칙으로 이뤄지니까,
더 기록할 것도 없었다.
이제 기존 값을 아시아판일 때의 상황은 다 바꿔줘야 하는데,
엑셀 시트 기반으로 Ctrl+C, Ctrl+V, Ctrl+H하는 프로그램을 만들었다가,
(결국 프로그래머는 직접 이 노가다를 하진 않지.. 뭔가를 만들어서 해버리지..)
이 짓 자체도 왜 컴퓨터한테 맡기지?
시트 결과로
replaceAll("
","
");
를 삽입하는 정규표현식 규칙을 만들어서 삽입하고 그냥 한번 돌려버려서 끝.
이제 아시아판도 잘 되는구나 싶어서 테스트해보니,
USA도 OK.
즉, 부모롬 Euro 960619에서 파생된 960619 영문버전은 다 같은 규칙으로 값들이 밀려났던 것.
덕분에 다른 수정롬도 모두 OK.
스테이지 진입시 몇 스테이지인지 뜨는 텍스트만은 유의미한 주소를 찾지 못해서,
그 부분만 24장의 이미지서칭을 남겨두고 있었는데,
결국 그 주소도 찾아서, 값들을 기록해서 사용.
이제 이미지 서칭은 완전 폐기.
아쉽게도, 여기에 관한 x,y 주소는 없는지 찾지 못해서
밀어버리진 못하고 아예 지워버리기만 할 수 있었음.
대신, 스테이지 3-B의 베스비아 강의 경우,
게임 내에서 깜빡거림 효과를 위해 스스로 값을 왔다갔다해대는데,
이걸 0으로 바꾸는 속도와 맞지 않아서 어차피 깜빡거림을 피할 수 없어서
그냥 번역문은 그 위치가 아니라, 아래에 배치.
그래서 스테이지 3-B만 원문과 번역문이 함께 뜸.
(원문 위에 두면 눈 아프게 거슬린다.)
한글화는 코딩과는 좀 다른 작업이구나 싶었다.
리버싱과 리소스 작업이 거의 전부이다.
리버싱해서 원하는 주소와 값을 찾는 것,
그리고 그에 해당하는 리소스를 만드는 것.
(현대의 게임이라도, 텍스트의 위치나, 창 크기 같은것 정해야 하니까)
그리고 해킹이라면 그걸 내부에 정착시키는 것까지.
삽질을 하느라 시간을 좀 할애해버렸지만,
경험으로 삼고, 방법의 한계선과 최적의 방안을 배운 수업료라고 생각.
해둔 게 아까워서 + 하기로 한건 결국 해내는 성격
으로 결국 마무리.
한 번 경험했으니, 굳이 또 해보고 싶진 않아ㅏㅏ...
'Diary' 카테고리의 다른 글
TransNOCR 1.8.0 업데이트 후기 (2) | 2023.03.02 |
---|---|
마트휴일 AI 스피커가 말해주기 (Google Action) (0) | 2021.05.11 |
AI 스피커와 연동 (0) | 2021.04.07 |
iOS 13.4.1의 버그를 아직 안 고치고 있다. (1) | 2020.05.01 |
잘못 입금된 돈을 돌려줬다. (0) | 2019.08.04 |
잘못된 정보가 있다면, 꼭 댓글로 알려주세요(비로그인 익명도 가능).
여러분의 피드백이 저와 방문자 모두를 올바른 정보로 인도할 수 있습니다.
감사합니다. -현록