한자 테이블에 한글을 삽입했더니 히라가나, 가타가나 다 보이고 좋은듯.. 반각 띄어쓰기가 안되고 마땅히 폰트 디멘젼 테이블 분석도 귀찮고 해서 영문 알파벳 싹 지워버렸다는..
조금 해보니 압축이 되어 있어서 그렇지 압축만 두번(LZS, Simple merge) 걷어내면 파일이 용도별로 분리되어 있어서 작업 자체는 참 쉬운 편이다
이래저래 진행은 재밌는데 계속해볼까 ㅡ_-
*EDIT :
여러 한글화팀 또는 한글화 동호인분들이 저작권 문제로 몸살을 하고 있다. 특히 현역에서 아직도 게임이 활발히 판매중인 PSP의 경우는 저작권법 단속이 더 빡빡할 것으로 추측된다. 실제로도 몬스터 헌터 한글화팀은 해외로 홈페이지를 피신시켜 그나마 지금까지 살아남았다는 얘기도 있으니 말이다.
우선 분명히 언급하자면 타자는 디스가이아2 게임의 분석을 순수하게 지적 욕구로 디비 파본 것이며, 1)한글화 패치를 완성할 일본어 실력도 안되고, 설령 2)완성한다 해도 패치를 배포할 의지가 전혀 없다.
리버스 엔지니어링에 대한 분석도 많이 된데다가 원체 쉬운 형태이고 타자가 가능성을 보였으니, 원하는 사람이 많고 이 시대에 영웅이 아직 존재한다면 한글날팀과 같은 용자분들께서 공개하거나 또다른 "Mr. Anonymous"에 의해 어둠의 루트로 돌지 않을까 기대는 된다.
일단 뭐 폰트만 바꿔보았다. UMDGen으로 풀어보니 여러가지 데이터파일이 나왔고 그중 START_JP.LZS 파일의 압축을 풀어서(http://ph0ebus.net/94) 나온 파일들 중에 FontB0000.txp / FontB0001.txp 이 두개의 파일에 폰트가 들어 있었다.
TXP는 니폰이치 소프트 게임에서 사용하는 이미지 포맷으로 보이는데, PS2 버전에서는 TX2, PSP 버전에서는 TXP를 사용하는 듯 보인다. 차후 이 포맷에 관한 포스팅을 올려보겠다.
한글 폰트는 개발 편의상 Air로 생성해서 덮어씌웠다. 처음에 포인터 주소를 잘못 읽어 엉뚱한 자리에 폰트 씌우고 실행해보니 반절만 한글로 나와서 다른 폰트가 또 있는 줄 알고 하루종일 삽질을 해댔다는 후문.. -_-;;
남은건 텍스트 변환, 그래픽 변환인데... 영문판 데이터가 덮어씌워지면 한번 시도해보고, 안되면 그냥 gg 칠지도.. 타자에게 아직 책임감은 없다~~
37 IBM EBCDIC - U.S./Canada 437 OEM - United States 500 IBM EBCDIC - International 708 Arabic - ASMO 708 709 Arabic - ASMO 449+, BCON V4 710 Arabic - Transparent Arabic 720 Arabic - Transparent ASMO 737 OEM - Greek (formerly 437G) 775 OEM - Baltic 850 OEM - Multilingual Latin I 852 OEM - Latin II 855 OEM - Cyrillic (primarily Russian) 857 OEM - Turkish 858 OEM - Multlingual Latin I + Euro symbol 860 OEM - Portuguese 861 OEM - Icelandic 862 OEM - Hebrew 863 OEM - Canadian-French 864 OEM - Arabic 865 OEM - Nordic 866 OEM - Russian 869 OEM - Modern Greek 870 IBM EBCDIC - Multilingual/ROECE (Latin-2) 874 ANSI/OEM - Thai (same as 28605, ISO 8859-15) 875 IBM EBCDIC - Modern Greek 932 ANSI/OEM - Japanese, Shift-JIS 936 ANSI/OEM - Simplified Chinese (PRC, Singapore) 949 ANSI/OEM - Korean (Unified Hangeul Code) 950 ANSI/OEM - Traditional Chinese (Taiwan; Hong Kong SAR, PRC) 1026 IBM EBCDIC - Turkish (Latin-5) 1047 IBM EBCDIC - Latin 1/Open System 1140 IBM EBCDIC - U.S./Canada (037 + Euro symbol) 1141 IBM EBCDIC - Germany (20273 + Euro symbol) 1142 IBM EBCDIC - Denmark/Norway (20277 + Euro symbol) 1143 IBM EBCDIC - Finland/Sweden (20278 + Euro symbol) 1144 IBM EBCDIC - Italy (20280 + Euro symbol) 1145 IBM EBCDIC - Latin America/Spain (20284 + Euro symbol) 1146 IBM EBCDIC - United Kingdom (20285 + Euro symbol) 1147 IBM EBCDIC - France (20297 + Euro symbol) 1148 IBM EBCDIC - International (500 + Euro symbol) 1149 IBM EBCDIC - Icelandic (20871 + Euro symbol) 1200 Unicode UCS-2 Little-Endian (BMP of ISO 10646) 1201 Unicode UCS-2 Big-Endian 1250 ANSI - Central European 1251 ANSI - Cyrillic 1252 ANSI - Latin I 1253 ANSI - Greek 1254 ANSI - Turkish 1255 ANSI - Hebrew 1256 ANSI - Arabic 1257 ANSI - Baltic 1258 ANSI/OEM - Vietnamese 1361 Korean (Johab) 10000 MAC - Roman 10001 MAC - Japanese 10002 MAC - Traditional Chinese (Big5) 10003 MAC - Korean 10004 MAC - Arabic 10005 MAC - Hebrew 10006 MAC - Greek I 10007 MAC - Cyrillic 10008 MAC - Simplified Chinese (GB 2312) 10010 MAC - Romania 10017 MAC - Ukraine 10021 MAC - Thai 10029 MAC - Latin II 10079 MAC - Icelandic 10081 MAC - Turkish 10082 MAC - Croatia 12000 Unicode UCS-4 Little-Endian 12001 Unicode UCS-4 Big-Endian 20000 CNS - Taiwan 20001 TCA - Taiwan 20002 Eten - Taiwan 20003 IBM5550 - Taiwan 20004 TeleText - Taiwan 20005 Wang - Taiwan 20105 IA5 IRV International Alphabet No. 5 (7-bit) 20106 IA5 German (7-bit) 20107 IA5 Swedish (7-bit) 20108 IA5 Norwegian (7-bit) 20127 US-ASCII (7-bit) 20261 T.61 20269 ISO 6937 Non-Spacing Accent 20273 IBM EBCDIC - Germany 20277 IBM EBCDIC - Denmark/Norway 20278 IBM EBCDIC - Finland/Sweden 20280 IBM EBCDIC - Italy 20284 IBM EBCDIC - Latin America/Spain 20285 IBM EBCDIC - United Kingdom 20290 IBM EBCDIC - Japanese Katakana Extended 20297 IBM EBCDIC - France 20420 IBM EBCDIC - Arabic 20423 IBM EBCDIC - Greek 20424 IBM EBCDIC - Hebrew 20833 IBM EBCDIC - Korean Extended 20838 IBM EBCDIC - Thai 20866 Russian - KOI8-R 20871 IBM EBCDIC - Icelandic 20880 IBM EBCDIC - Cyrillic (Russian) 20905 IBM EBCDIC - Turkish 20924 IBM EBCDIC - Latin-1/Open System (1047 + Euro symbol) 20932 JIS X 0208-1990 & 0121-1990 20936 Simplified Chinese (GB2312) 21025 IBM EBCDIC - Cyrillic (Serbian, Bulgarian) 21027 Extended Alpha Lowercase 21866 Ukrainian (KOI8-U) 28591 ISO 8859-1 Latin I 28592 ISO 8859-2 Central Europe 28593 ISO 8859-3 Latin 3 28594 ISO 8859-4 Baltic 28595 ISO 8859-5 Cyrillic 28596 ISO 8859-6 Arabic 28597 ISO 8859-7 Greek 28598 ISO 8859-8 Hebrew 28599 ISO 8859-9 Latin 5 28605 ISO 8859-15 Latin 9 29001 Europa 3 38598 ISO 8859-8 Hebrew 50220 ISO 2022 Japanese with no halfwidth Katakana 50221 ISO 2022 Japanese with halfwidth Katakana 50222 ISO 2022 Japanese JIS X 0201-1989 50225 ISO 2022 Korean 50227 ISO 2022 Simplified Chinese 50229 ISO 2022 Traditional Chinese 50930 Japanese (Katakana) Extended 50931 US/Canada and Japanese 50933 Korean Extended and Korean 50935 Simplified Chinese Extended and Simplified Chinese 50936 Simplified Chinese 50937 US/Canada and Traditional Chinese 50939 Japanese (Latin) Extended and Japanese 51932 EUC - Japanese 51936 EUC - Simplified Chinese 51949 EUC - Korean 51950 EUC - Traditional Chinese 52936 HZ-GB2312 Simplified Chinese 54936 Windows XP: GB18030 Simplified Chinese (4 Byte) 57002 ISCII Devanagari 57003 ISCII Bengali 57004 ISCII Tamil 57005 ISCII Telugu 57006 ISCII Assamese 57007 ISCII Oriya 57008 ISCII Kannada 57009 ISCII Malayalam 57010 ISCII Gujarati 57011 ISCII Punjabi 65000 Unicode UTF-7 65001 Unicode UTF-8
이렇게 목록으로 써놓으니 많이도 나왔다. 통칭 폐인전기 디스가이아라 불리우는 니폰이치의 불멸의 소프트.
우선 짬짬히 마계전기 디스가이아 2 PSP판을 열어보았다.
디스가이아2가 유난히 자료가 많았던 이유
디스가이아2가 2009년 초에 PSP에 일본어 판으로 이식되었고, 이후 영문판이 출시되기까지 시간차가 발생하는데, 이 시간차동안 PSP 펌웨어가 대폭 업그레이드되고, 커펌 사용자들의 호프였던 DarkAlex군께서 어둠의 생활을 접겠다 선언하여 정식 펌웨어가 6.x대를 달리고 있는 지금에도 커펌 사용자들은 5.00m33-6을 사용하고 있으니, 영어권 커펌 유저들은 5.55 이상에서만 구동 가능한 디스가이아2 영문판과 5.00 이상에서 구동 가능한 디스가이아2 일어판을 양손에 올려놓고(사실은 두개의 폴더에 다운받아놓았겠지? 나도 정품 유저라구~ 우쭐우쭐~~) 저울질한다. 그나마 비슷한 한자언어권의 우리나라 사람들도 못배우면 까만건 글씨요 하얀건 화면 바닥인데, 양키들 오죽 힘들까...
그래서 시작한 그들의 뻘짓거리.. 영문판 각종 파일을 일어판 이미지에 덮어씌워 구동시키는 삽을 든 것이다. 물론 이나마도 최근엔 5.55 이상의 게임을 5.50 이하에서 구동 가능하게 해주는 디크립터가 나와 흐지부지되었다.
타자가 참조한 자료는 대부분이 위 관련 자료였으며, 그나마 한 1/10 정도는 2CH에서 참조했다.
타자 역시도 영문판과 일어판을 비교하는 작업으로 시작했다.
...
...
답이 안나온다..
파일 목록도 워낙 다르고, Hex Compare 해서 같은 파일은 싹싹 지워가면서 폼나게 진행하려 했는데, 여기저기 스크립트가 널부러져 있다. 심지어 확장자가 LZS인 LZSS 압축 파일까지 등장!!
.....
접근을 바꿔 디스가이아1 PS2 한글판을 열어보았다. 여기서 한글 스크립트 추출하면 PSP, NDS 버전은 날로 먹겠지 하는 게으른 생각에.. 더 바란다면 PS2 한글판과 일어판을 비교해서 포인터 패턴 분석이라도 해서 2에 적용해보려는 생각....
독립엔진은 별도로 JSON 어댑터를 제공해주어서 특정 명령 호출까지는 문제없이 진행되었다. 다만, 미디어 엔진이다 보니 명령 호출 후 미디어 인코딩 등의 시간이 오래 걸리는 프로세스가 많았고 이 프로세스가 끝나는 2~30분 이후까지 Flex RPC 스레드를 물고 있다가 결과 핸들러를 발생할 수가 없는 상황이 발생했다. 즉, JSON 호출과 프로세스 결과 이벤트가 각각 다른 스레드를 가져야 하는 상황.
아래와 같은 내용으로 개발은 진행된다.
JSON 호출 (Java Service)
URL url = new URL("http://{ENGINE_SERVER_IP}/context/engine"); URLConnection connection = url.openConnection(); connection.addRequestProperty("tid", (String)params.get("tid")); // Timestamp, Session ID 등으로 Unique한 ID값을 생성하여 리턴 - 결과 핸들러의 filter key가 됨 (.. 필요한 파라미터를 더 추가하던지 어쩌던지 ..)
미디어 엔진에서는 위의 tid 값을 가지고 있다가 프로세스 완료후 결과 핸들러를 능동적으로 호출하면서 파라미터에 tid를 재전송한다. 이제 엔진에서 결과값을 리턴할 서블릿을 구성해보자.
Result Handler (Servlet)
String tid = request.getParameter("tid"); if (tid != null) { Long ts = new Date().getTime(); AsyncMessage msg = new AsyncMessage(); msg.setDestination(DESTINATION_ID); msg.setClientId(tid); msg.setMessageId("msg" + ts); msg.setTimestamp(ts); msg.setHeader(AsyncMessage.SUBTOPIC_HEADER_NAME, tid); HashMap map = new HashMap(); Enumeration params = request.getParameterNames(); while(params.hasMoreElements()) { String pName = (String)params.nextElement(); String pValue = request.getParameter(pName); map.put(pName, pValue); } msg.setBody(map); MessageBroker.getMessageBroker(null).routeMessageToService(msg, null); }
엔진에서 프로세스가 완료되면 위 서블릿을 호출하며, 서블릿에 지정된 request parameter들을 HashMap으로 변형해서 BlazeDS의 Message로 발생시킨다. 이제 Flex에 Consumer를 설정해야겠지?
호출/결과 (Flex)
public function PhAsyncRemoteProcedure(producerDestination:String, consumerDestination:String) { super(); consumer = new Consumer(); consumer.destination = consumerDestination; consumer.addEventListener(MessageFaultEvent.FAULT, faultHandler); consumer.addEventListener(MessageEvent.MESSAGE, messageHandler); producer = new RemoteObject(producerDestination) producer.addEventListener("result", produceResultHandler); }
private var producer:PhRemoteObject; private var consumer:Consumer;
// 최초 json 호출 public function call(parameters:Object):void { producer.call(parameters); }
// 생성된 tid로 Consumer 설정 private function produceResultHandler(event:ResultEvent):void { var ev:SomeEvent = new SomeEvent("call"); ev.result = event.result; dispatchEvent(ev); consumer.subscribe(String(event.result.tid)); }
// 최종 결과값이 발생했을 때 처리 private function messageHandler(event:MessageEvent):void { var ev:SomeEvent = new SomeEvent("result"); ev.result = event.message.body; dispatchEvent(ev); }
Flex에서 호출하고 받는 부분이다. 주목할 부분은 subTopic으로 해당 프로세스 스레드를 구분하여 메세지 처리하는 부분이다.