계속 해서 세번째 글을 올립니다.
이전글은 아래 link를 이용하세요

원래는 짧게 설명 될듯 생각 했는데 - 글을 작성하다 보니 의외로 길어 졌습니다.
그냥 patch data만 올려도 되겠지만, 나름의 뒷구멍 파시는 분에게 혹시나 참고 자료가 될듯 하여 자세히 기술하다보니 많이 길어 졌습니다.


[2011-01-25]
맵피고(맵피Go . MappyGo) 관련 패치는 아래 URL로 이동 하세요.


지난글에서 해결한 사항은 아래와 같습니다.
첫번째글: Mappy 실행 후 첫 지도 화면 보이기
두번째글: GPS정보 화면 제대로 보이기

나머지 해결해야 할 문제: GPS 인식 직후 화면 먹통 문제

오늘은 마지막으로 "GPS 인식 직후 제대로 보이기" 입니다.
이미 지난글에 언급했듯이 GPS 인식 후 문제도 결국 두번째글에서 해결한 사항과 동일합니다.
맵피는 하나의 window에 대해서 지도도 보이고 dialog box도 보입니다 그런데 어떤 상황에서 이 공용 window의 크기가 뒤틀려 버리고, 이후로는 지도를 영영 볼수가 없는게 문제의 핵심이었습니다.

그럼 이미 지난 글에서 해결책으로 사용한 MoveWindow 관련 동작이 문제의 핵심이라 생각 할 수 있습니다.
무작정 MoveWindow를 검색 해 봅니다. IDA에서 MoveWindow 호출 부분에서 'X' 키를 누르면 모든 MoveWindow 호출 위치가 짠~ 하고 나타 납니다.
다행이 모두 6곳만이 있습니다. 전체 code에서 단지 6개면 시도 해 볼만한 게임입니다!

그 중에 한곳(맨 먼저 등장)은 이미 지난글에서 패치한 그 부분 입니다.
그래서 후보군은 5개로 좁혀 집니다.

쭉 정리하면 아래와 같습니다. [MoveWindow 호출 부분 6곳]
이미 MoveWindow 기능은 이전글에서 파악 했기에, 쭉 나열하고 부차적으로 설명 하겠습니다.
실은 아래 내용은 제가 삽질 하면서 기록한 내용을 거의 그대로 가져 왔습니다.
이런 일에는 모든 작업을 기록을 해 두어야 좀 쉽습니다.(머리가 나빠 하루 지나면 까먹는다는 ㅎㅎ)
MoveWindow는 단지 6개 부분에서 호출 됨

[1] MAIN_DIALOG_GPS_INFORMATION:loc_277A8 --> 완료!: GPS정보 - Dialog box 부분 참조
       BL   MoveWindow   --> 이미 수정한 부분
원본:  A7 23 08 EB 01 10 A0 E3
수정:  00 00 80 E3 01 10 A0 E3

[2] sub_4AAC8+54 : 무언가 중요해 보임 - 이 함수 호출 후 / Update window 부르는 함수확인
      .text:0004AB1C  BL  MoveWindow    부분을 NOP 처리 해 보자
      ORRR1, R1, #0   00 10 81 E3 로 설정 하기
원본:  CA 96 07 EB 28 D0 8D E2 70 80 BD E8
수정:  00 10 81 E3 28 D0 8D E2 70 80 BD E8

[3] sub_DA550+44 : 이넘도 뭔가 수상함 - GetTickCount 부분에서도 호출 됨
      특히 EualRect 등으로 확인 후 이 함수를 호출하고 있음.
      ORRR1, R1, #0   00 10 81 E3 로 설정 하기
원본:  2C 58 05 EB 08 D0 8D E2 10 80 BD E8
수정:  00 10 81 E3 08 D0 8D E2 10 80 BD E8


아래 3개는 동일 함수내에 즉 같은 의미의 MoveWindow 호출 (3 case에 따른 중복 호출)
 ----> 원본 code를 똑똑하지 않게 작성 했다는 의미입니다. ['도배' 했다는 거죠 ㅋㅋ]
패치 하지 말것 - 최초 Intro 화면에 대한 가로/세로 변환임 - 그냥 두어야 가로로 인트로가 나옴!
 -----> ORR  R0, R0, #0   00 00 80 E3

[4] sub_1F9810+184 : Main Frame window title text 등을 설정 하는 듯 - 이넘에 관심 가지자!
BL      MoveWindow
원본:  2C DB 00 EB 00 00 96 E5
수정:  00 00 80 E3 00 00 96 E5

[5] sub_1F9810+1EC :
BL      MoveWindow
원본:  12 DB 00 EB 00 00 96 E5
수정:  00 00 80 E3 00 00 96 E5

[6] sub_1F9810+248 :
BL      MoveWindow
원본:  FB DA 00 EB 00 00 96 E5
수정:  00 00 80 E3 00 00 96 E5

자~ 마직막을 달려 가고 있습니다.

[1]은 이미 이전글에 패치를 하여 GPS정보 dialog를 제대로 보이게끔 완성 했습니다.
나머지 MoveWindow를 모조리 없애 버리고 확인 하면 좋겠지만... 무언가 삑사리가 발생하겠죠.

그래서 아래와 같이 패치를 종류별로 나열 했습니다.
당연 [1]번 패치 까지 설정한 상태에서 아래의 2가지 조합을 먼저 처리해서 test 해 봅니다.

1. [2]번 패치 적용
실행 했습니다. GPS 인식도 해 보았습니다.
넵! 아무런 문제가 없이 동작 완료 했습니다. 끝을 봤다고 할까요

2. [3]번 피치 적용
실행 했습니다. 그런데 320x240 화면이 세로로 중앙에 표시가 되더군요 ㅋㅋㅋ
넵! 실행에는 문제가 없습니다. 그런데 Title / Softkey가 아래에 있는 app.의 것이 보이기 때문에 조작 실수가 발생 할 듯 하여 - 이 버전을 사용 안하는게 좋을 듯 합니다.


그리고~ 나머지 [4], [5], [6]은 셋트 메뉴이므로 [2][4][5][6] 과 [3]
[4][5][6] 두개를 비교 해 보았습니다.
바꾼것은 Intro 화면이 가로가 아닌 세로로 나오더군요 ㅋㅋㅋ
넵 그래서 최종적으로 [2]번 사항만 적용 하면 된다는 것이 결론입니다.

그런데 이 [2] 패치 하면서 맵피 동작을 살펴 봤는데 - GPS 인식 직후에 화면이 1dot 정도 구성이 달라 지더군요 - 각족 button이 1pixel인가 위로 올라 갑니다. 즉 화면에 대해서 이상한 짓을 한다는 것이 제 눈에 보였고 - 결국 MoveWindow가 그 단서라는 것은 이 현상을 보고서도 확인이 된 것이죠.


자 이제 끝입니다... 최종 정리 하겠습니다.
글이 길어서 어떻게 패치 하라는 것인지 헷갈릴 듯 하여... 최종 종합 정리 입니다.



320x240 강제 설정 패치 부분
"차례"  "파일offset"
     [ 원본 hex code ]  --> [ 수정 hex code ]

1  0x038684
   [ F9 9C 07 EB ] --> [ 05 0D A0 E3 ]

2  0x038694
   [ F5 9C 07 EB ] --> [ F0 00 A0 E3 ]

3  0xC97E0
   [ A2 58 05 EB ] --> [ 05 0D A0 E3 ]

4  0xC97F0
   [ 9E 58 05 EB ] --> [ F0 00 A0 E3 ]

5  0xCA8C4
   [ 69 54 05 EB ] --> [ 05 0D A0 E3 ]

6  0xCA8D4
   [ 65 54 05 EB ] --> [ F0 00 A0 E3 ]



GPS정보 dialog 제대로 보이게 패치
  [ A7 23 08 EB 01 10 A0 E3 ] ---> [ 00 00 80 E3 01 10 A0 E3 ]



GPS 인식 직후 화면 제대로 보이게 패치
  [ CA 96 07 EB 28 D0 8D E2 70 80 BD E8 ]   ---> [ 00 10 81 E3 28 D0 8D E2 70 80 BD E8 ]



[안내]
아래 제공되는 파일은 맵피 PDA 라이센스를 소유 하고 있으나 M&Soft 에서 이해할 수 없는 정책을 주장하여 M480, M4800 에서는 사용 할 수 없는 호환성을 해결하고자 개인적으로 만든 파일 입니다.
관련 법을 준수하시기 바랍니다.
컴퓨터프로그램 보호법 - 역분석 관련 법

제12조의2 (프로그램코드역분석)
①정당한 권원에 의하여 프로그램을 사용하는 자 또는 그의 허락을 받은 자가 호환에 필요한 정보를 쉽게 얻을 수 없고 그 획득이 불가피한 경우 당해 프로그램의 호환에 필요한 부분에 한하여 프로그램저작권자의 허락을 받지 아니하고 프로그램코드역분석을 할 수 있다.
②제1항의 규정에 의한 프로그램코드역분석을 통하여 얻은 정보는 다음 각호의 1에 해당하는 경우에는 이를 사용할 수 없다.
   1. 호환 목적외의 다른 목적을 위하여 이용하거나 제3자에게 제공하는 경우
   2. 프로그램코드역분석의 대상이 되는 프로그램과 표현이 실질적으로 유사한 프로그램을 개발·제작·판매하거나 기타의 프로그램저작권을 침해하는 행위에 이용하는 경우
      [본조신설 2001·1·16][[시행일 2001·7·17]]

이 파일을 이용해서 맵피를 사용 하기 위해서는
반드시 맵피 PDA 라이센스를 소유 하고 있으며, 또한 Mappy 전체 이미지를 정상적으로 download하신 분 만이 사용이 가능 합니다.

여기서 안내드리는 내용은 직접 patch를 할 수 있는 정보와 patch용 요약자료만 공유 합니다.
패치 프로그램과 Mappy라이센스, Mappy 인스톨 파일은 개인 소유의 것을 이용하셔야 합니다.


Patch 파일은 Free software인 VPatch 를 사용 했습니다. Google 등의 검색엔진을 이용하셔서 개인이 구하셔야 합니다.
이 프로그래과 제공하는 data를 이용하여 발생하는 법적인 문제에 대해서는 사용하는 당사자들의 책임임을 밝혀 둡니다.

아래 파일에 대해서는 그 어떠한 질문에 대해서도 답변을 드리지 않습니다.

패치요약 파일:
위 파일은 VPatch 라는 프로그램을 설치하고난 뒤에 전용 프로그램을 이용하시면 됩니다.
*당연히 Mappy 5.5.1 버전 원본이 있어야 합니다.
*Patch 실행 법은 VPatch 설명서를 참고 하세요.
 
VPATCHPROMPT.EXE (patchfile) (sourcefile) (outputfile)




** 반드시 RealVGA 혹은 ForceHires 유틸리티를 사용 하셔서 96 dpi 모드로 실행 하셔야 합니다.

** 그리고 그냥은 GPS연결이 제대로 안됩니다.
꼭 GpsGate등의 유틸리티로 새로운 포트를 할당하고, Mappy는 그 포트를 이용 하도록 하셔야 합니다.
이 부분은 맵피의 버그라고 봅니다. 예전 M4300 사용 때에도 부팅 직후 GPS연결하면 먹통이 되었습니다.
** 상황에 따라 맵피가 먹통 됩니다.(아주 간혹 발생) 이 경우 다시 부팅하고서 실행 해야 하더군요.
역시 맵피 자체의 문제로 인식이 됩니다.


실행화면 캡쳐 내용입니다.


















.
이전글에 이어서 계속 합니다.

패치를 위해 코드 여기저기를 헤메고, 아이디어를 확인 하고 정신 없이 진행 하고, 틈틈이 정리는 해 두었는데 - 역시나 글로 다시 깔끔하게 정리 하려니 시간과 노력이 많이 필요 하군요.


자~ 어제글에 이어 오늘은 M480,M4800(미라지)에서 맵피(Mappy)를 정상적으로 사용하기 위한 나머지 내용을 정리, 작성 하겠습니다.

패칭을 위해서는 여러 지식도 필요로 하지만 - 원본 code없이 assembly로만 구성된 기계어 수준의 코드에서 어떠한 기능을 찾는 것은 - 나름의 "아이디어"가 있어야 합니다.
이번일도 이러한 "아이디어"를 생각하고 해당하는 code를 찾고, 그 code를 이리저리 바꾸어 보는 것으로 완료를 했다고 할 수 있습니다.

어제까지는 Mappy화면을 제대로 띄우는 동작 까지 했습니다.

그런데 문제가 있다고 언급 드렸죠!
네! - 어제 수정된 내용 - 즉 강제로 320 x 240으로 화면 크기를 조절하는 것으로 대부분의 동작은 만족하나, GPS정보 화면이 표시되지 않으며, 더구나 GPS 연결이 되고 난 직후에 역시 화면이 먹통이 되는 문제가 있다고 했습니다.

이 문제를 해결하려고 합니다.


다시금 문제를 분석 해 봅니다.
알고보면 현상이 처음 맵피가 실행 된 직후의 증상과 다른 것이 없습니다.
즉 분명 터치 입력은 되고 있으나, 지도 화면 등이 먹통으로 내용이 표시 되지 않는 다는 것이죠.

그렇다면 첫번째 해결한 내용과 동일한 문제가 있다는 것이죠.
즉 특정 상황에서 320x240으로 유지되던 화면이 320x320 혹은 240x320 등등으로 320x240이 아닌 화면으로 변형 되었을 것이라고 가정을 할 수 있습니다.

그런데 이미 320x240으로 설정 하게끔 몇개의 code를 patch를 했습니다.
그런데도 동일 문제가 있다는 것입니다.
난감하죠... 첫번째 해결책이 모자라는 결론이기 때문이죠.

그래서 GPS 설정 버턴 [나침반 아이콘 누른 직후, 위성 아이콘 누르기/혹은 위성 아이콘 바로 누르기] 결과로 보이는 "먹통"화면에 대해서 터치를 여기저기 눌러 보았습니다.
즉 눈에는 보이지 않으나 분명 touch에 반응하는 부분이 있을 것이라 생각을 한 것입니다.

넵! 역시나 맞습니다. 눈에는 보이지 않으나 분명 GPS 정보 화면이 표시되고 있었습니다.
다만 그 형태가 최초의 320x240이 아니라 240x320 형태로 기대와 다른 엉뚱한 위치에 버턴들이 위치해 있더군요.

자~ 여기서 단서를 하나 잡았습니다.
특정 상황에서 Window의 크기를 임의로 수정하는 부분이 있다는 것입니다.

[아래 내용은 Visual Studio Remote Tools에 있는 "원격 감시" 프로그램으로 확인 할 수 있습니다.]
실제 Mappy에 대해서 window 구조를 확인 해 보았는데 - 단지 두개의 window만 사용 하는 것으로 보였습니다.
심지어 전체 화면을 구성하는 dialog에서도 말이죠!
즉 지도화면의 window에서 특정 전체 화면을 이루는 dialog 화면은 새로운 window를 띄우는 것이 아니라 기존의 지도화면을 이루고 있는 window를 공유 하고 있는 것이죠.

자 이제 이야기가 맞아 들어 갑니다.
Mappy는 지도 View를 구성하는 Window가 있는데, 다른 전체 화면의 dialog도 이 window를 공유하고, M480x와 같은 320x320 해상도의 환경에서는 특정 code부분에 의해서 임의로 240x320 등으로 Window 크기를 임의로 변형하는 문제가 있다는 것입니다.


우선 GPS정보 화면을 바로 보기 위해서 assembly code에서 해당 code 부분을 찾아 보았습니다.
그냥 보아서 신이 아닌이상 어떻게 이 많은 code에서 GPS정보 화면 부분을 찾겠습니까?

또 단서를 확인 해야 합니다.
GPS정보 화면은 아래와 같은 내용이 표시 됩니다.


단서들이 주렁주렁 달려 있습니다!
수신기 상태, 설정, 정보에 있는 string 값들이 바로 단서들입니다.

한글은 유니코드라 IDA에서 보기 힘들므로 영문과 숫자 출력 부분이 만만한 넘들입니다.
즉 아래와 같은 string을 예상 할 수 있습니다.
  ON, OFF, 1D, 2D, 3D, %d km/h, %d:%2d:%2d

감이 안오신다구요? 감이 오셔야 직접 패칭 작업을 하실 수 있습니다. 혹시 직접 해 보실 분은 감이 오도록 '정성'을 들이 실 필요가 있을 것 같습니다.

자~ 그리고 그 부분을 제대로 찾았습니다.

그리고 해당 code 부분의 앞뒤를 마구 뒤져 봅니다~ 쭈욱 봅니다. 함수 이름에만 집중 해서 말이죠...
무언가 감흥이 오는 함수가 있을까 하고...
보았더니 OnInitDialog 부분이 눈에 보입니다.
넵 - MFC로 된 Dialog이므로 위 함수가 당연히 있다는 것이죠.

그리고 또 주변을 둘러 봅니다.
SHInitDialog / SHFullScreen 등의 함수 호출이 눈에 띄입니다.
그리고 그 주변에 불쑥 나타나는 GetWindowRect, MoveWindow가 제 눈안을 파고 듭니다!!!
눈이 또릿또릿 해 지더군요! 단서 포착입니다!

해당 부분을 리스팅 하면 아래와 같습니다 - 몇몇 부분은 미리 뒤져서 이름 수정 한 부분도 있습니다.
[지금 언급 드리는 내용은 전체 삽질에서 성공한 삽질 위주로 설명 드리는 것임을 감안 해 주세요]
.text:000276E4 MAIN_DIALOG_GPS_INFORMATION
.text:000276E4
.text:000276E4 nHeight         = -0x50
.text:000276E4 bRepaint        = -0x4C
.text:000276E4 var_48          = -0x48
.text:000276E4 var_44          = -0x44
.text:000276E4 var_40          = -0x40
.text:000276E4 var_3C          = -0x3C
.text:000276E4 var_38          = -0x38
.text:000276E4 pshidi          = -0x34
.text:000276E4 X               = -0x24
.text:000276E4
.text:000276E4                 STMFD   SP!, {R4-R7,LR}
.text:000276E8                 SUB     SP, SP, #0x3C   ; nHeight
.text:000276EC                 MOV     R6, R0
.text:000276F0                 BL      _OnInitDialog_CDialog__UAAHXZ ;
                             CDialog::OnInitDialog(void)
.text:000276F4                 BL      _AfxGetModuleState__YAPAVAFX_MODULE_STATE__XZ ; AfxGetModuleState(void)
.text:000276F8                 LDR     R1, [R0,#4]
.text:000276FC                 LDR     R0, [R1,#0x20]
.text:00027700                 BL      CFrameWnd__GetActiveView
.text:00027704                 LDR     R5, [R0,#0x48]
.text:00027708                 MOV     R1, #0x2340
.text:0002770C                 MOV     R2, #0
.text:00027710                 ORR     R1, R1, #8
.text:00027714                 MOV     R0, R5
.text:00027718                 BL      sub_11097C
.text:0002771C                 MOV     R1, R0
.text:00027720                 ADD     R0, R6, #0xD8
.text:00027724                 BL      _Attach_CGdiObject__QAAHPAX_Z ; CGdiObject::Attach(void *)
.text:00027728                 LDR     R3, [R6,#0x20]
.text:0002772C                 MOV     R0, #0x10       ; SHIDIF_FULLSCREENNOMENUBAR
.text:00027730                 STR     R0, [SP,#0x50+pshidi.dwFlags]
.text:00027734                 MOV     R7, #1
.text:00027738                 ADD     R0, SP, #0x50+pshidi ; pshidi
.text:0002773C                 STR     R7, [SP,#0x50+pshidi]
.text:00027740                 STR     R3, [SP,#0x50+pshidi.hDlg]
.text:00027744                 BL      SHInitDialog
.text:00027748                 LDR     R0, [R6,#0x4C]
.text:0002774C                 MOV     R1, #0          ; fShow
.text:00027750                 LDR     R0, [R0,#0x20]  ; hwndCB
.text:00027754                 BL      CommandBar_Show
.text:00027758                 LDR     R0, [R6,#0x20]  ; hwndRequester
.text:0002775C                 MOV     R1, #0xA        ; dwState
.text:00027760                 BL      SHFullScreen
.text:00027764                 LDR     R0, [R6,#0x20]  ; hWnd
.text:00027768                 BL      SetForegroundWindow
.text:0002776C                 LDR     R0, [R6,#0x20]  ; hwnd
.text:00027770                 MOV     R1, #1          ; nCmdShow
.text:00027774                 BL      ShowWindow
.text:00027778                 LDR     R0, [R6,#0x20]  ; hwnd
.text:0002777C                 ADD     R1, SP, #0x50+X ; prc
.text:00027780                 BL      GetWindowRect
.text:00027784                 LDR     R0, [SP,#0x38]
.text:00027788                 LDR     R4, [SP,#0x30]
.text:0002778C                 ADD     R2, R0, #0x1A
.text:00027790
.text:00027790 loc_27790                          ; DATA XREF: sub_1812B4+1AC
.text:00027790                 LDR     R1, [SP,#0x50+X] ; X
.text:00027794                 LDR     R3, [SP,#0x34]  ; nWidth
.text:00027798                 STR     R2, [SP,#0x50+nHeight]
.text:0002779C                 SUB     R2, R4, #0x1A   ; Y
.text:000277A0
.text:000277A0 loc_277A0                          ; DATA XREF: sub_17FDDC+6E4
.text:000277A0                                    ; sub_17FDDC+8C0
.text:000277A0                 LDR     R0, [R6,#0x20]  ; hWnd
.text:000277A4                 STR     R7, [SP,#0x50+bRepaint]
.text:000277A8
.text:000277A8 loc_277A8                         ; DATA XREF: sub_17FDDC:loc_1805A4
.text:000277A8                 BL      MoveWindow
.text:000277AC                 MOV     R1, #1
.text:000277B0                 MOV     R0, R6
.text:000277B4                 BL      sub_27930
.text:000277B8                 MOV     R0, R6
.text:000277BC
.text:000277BC loc_277BC                         ; DATA XREF: sub_1C2B14+358
.text:000277BC                                   ; sub_1C2B14+37C
.text:000277BC                 BL      GPS_Information
...

눈여겨볼 부분이 3군데 있습니다. 아래 함수 입니다.
  SHInitDialog
  GetWindowRect
  MoveWindow

공부차원에서 SHInitDialog를 MSDN에서 찾아보면 아래와 같습니다.
SHInitDialog
This function is primarily used to create a full-screen dialog box with the OK button in the navigation bar. The user interface for Smartphone uses many full-screen dialog boxes. Because the navigation bar has been moved to the top of the screen, the Done button has been visually removed from full-screen dialog boxes and replaced with an OK button in the navigation bar.
BOOL SHInitDialog (
  PSHINITDLGINFO pshidi
);

PSHINITDLGINFO 는 아래값을 사용하는 것으로 확인을 했습니다.
SHIDIF_FULLSCREENNOMENUBAR
  Sizes the dialog box FULL screen. Does not leave room at the bottom for a menu bar

말은 길었는데, 결국 화면 전체를 덮어 버리는 FullScreen처리를 하는 API호출입니다.
우리가 문제가 되었던 그 dialog를 설정하는것이 확실 함을 판단 할 수 있습니다.

자  다시 본래의 문제를 깨우치면 - 화면이 유지되지 못하고 다른 크기로 window가 '변신'한다는 것이죠!
넵 그 변신 code는 위에서 언급한 나머지 두 함수 호출에 의해서 행해짐을 추정할 수 있습니다.
GetWindowRect와 MoveWindow죠.

그냥 DialogBox만 띄울것이지 왜! 왜! Window크기를 막 돌려 버리냐는 것이죠! 왜!
앞서 언급 드렸지만 맵피는 지동 출력용 window를 dialog에서도 공유한다고 했습니다. 이런 공유자원을 이 dialog code에서 맘대로 MoveWindow를 하는 code가 있다는 것이 문제라는 것이죠.

자 그러면 해결 방법이 보입니다.
MoveWindow를 없애 버리면 되는 것이죠.

ARM에서 아쉬운 것이 x86에서 매우 유용한 NOP 명령어가 없습니다. NOP의 경우 1byte 쨔리라 땜방 처리에는 아주 편한 명령어 입니다.
그래서 ARM에서는 의미없는 연산으로 대체 해야 합니다. 아래 명령으로 대체 하면 됩니다.
ORR  R0, R0, #0   ==  00 00 80 E3

위에 나열된 리스트에서 MoveWindow를 없애 버립니다.
.text:000277A8           BL      MoveWindow  --> ORR R0, R0, #0 으로 패치
.text:000277AC           MOV     R1, #1

Patch를 위한 원본 Hex data는 아래와 같습니다. (유일하므로 찾아서 수정 하면 됩니다)
  A7 23 08 EB 01 10 A0 E3 

아래처럼 patch 합니다.
  00 00 80 E3 01 10 A0 E3

아래 부분만 수정하면 이번 설명에서 해야할 패치는 모두 다 입니다.
[A7 23 08 EB 01 10 A0 E3 ] --> [ 00 00 80 E3 01 10 A0 E3 ]


자~ 그리고 다시금 수정한 파일을 M480x 혹은 에뮬레이터에서 실행 해 봅니다.

냅!
예상한 대로 잘 표시 됩니다.
 앞서 캡쳐한 화면은 에뮬레이터에서 수정한 파일 실행 후 표시된 내용입니다.

이제 모든것이 다 된것 같습니다.
이제 GPS인식이 남았습니다.

그런데 역시나 맵피의 시리얼 포트 설정 문제인지 아무리 아무리 GPS설정을 잘해 주어도 내장 GPS를 제대로 잡지 못합니다. (iNavi도 이런 증상은 동일하다고 하더군요)

그래서 유명한 GpsGate라는 프로그램을 동원 해야 합니다.
이부분 까지는 맵피를 직접 수정하는 것이 쉽지 않기에 - 그냥 GpsGate를 사용 하도록 합니다.
(저도 그냥 GpsGate 사용! - 소스 없이 이런 버그 까지 고치는 것은 너무나 괴로울 것 같습니다)

그리고 맵피를 실행하고, GPS를 잡아 봅니다!
넵! GPS 잘 잡히더군요.

하지만 또 다른 문제가 등장 했습니다.
GPS인식 직후 또 다시 동일 문제 - 즉 화면 먹통이 되어 버렸습니다 @#!%#^$!%^
이쯤되면 짜증이 막~ 밀려 오죠 - 넵 진짜 짜증 '지대로' 입니다.
그러나 화면 먹통 문제는 앞서 언급한 부분에서 우리가 한번 해결 했습니다.

네! MoveWindow를 없애 버리면 해결 했던거죠.


이 부분은 또다시 별도의 글로 계속 정리 하도록 하겠습니다.
헥헥 - 이번글은 예상보다 길어진듯 합니다. 물론 실제 삽질은 몇배는 길었습니다.

----- TO BE CONTINUE~
다음글 보기


참고 자료

Windows CE Remote Spy 결과 - 단지 2개의 Window만 존재 확인


안녕하세요~

제가 블로그 살림살이 한 이후로 원래 제 분야인 S/W 쪽은 전혀(!) 다루고 있지 않았습니다. 이번에 작업한 내용도 소개 드리고, 자동차 내용(특히 QM5)과 더불어 S/W 쪽도 올리는 기념으로 M480,M4800 사용자를 위한 맵피 사용 방법을 소개 드립니다.

M480x를 소유하시고 이전에 맵피 라이센스를 가지고 있는분들은 아시겠지만!
맵피가 작동되지 않습니다. RealVGA등으로 강제로 해상도를 낮추어도 - 실제 지도 화면조차 볼 수가 없었습니다.



관련하여 많은 사용자들이 M&Soft 에 요구도 하고, 항의도 하고, 심지어 애원도 했지만 - 답변은 매우 썰렁하다 못해 불쾌한 내용만 있었습니다. 즉 WM5 / WM2003 이 아니라 정식지원 안하고, 향후 기기업체와.... 등등의 구차한 변명만 답으로 올라 왔습니다.
간단히 정리하면 "돈도 안되는데 구지 예전 라이센스 사용자를 위해 320x320 해상도 제작은 배째라"로 표현 할 수 있다는 것이죠.

그렇습니다. 그렇다고 이미 가지고 있는 라이센스 팔기도 그렇고 - 답답한 제가 한번 삽질을 해 보았습니다.
현재 저는 이벤트로 받은 '파인드라이브'를 사용하기 때문에 차에서 구지 M480x에서 맵피가 없어도 되나, 실제 생활중에 지도 확인을 자주하던 생활 패턴으로는 답답하더군요.

실행 결과 Video 부터 소개 드립니다.



집에 캠코드가 없는 관계로(그렇다고 M4300 동영상 화질을 올리기에는 제가 용납을...) WM 6 320x320 해상도의 에뮬레이터에서 수정한 Mappy를 직접 실행 해 보았습니다.
M480x와는 달리 기본동작이 아닌 파일 저장 동작에는 약간에 문제가 있긴 하지만 - 화면 동작에는 무리 없는 결과를 확인 할 수 있습니다. 당연히 M480x에는 전기능 무사 동작 합니다.

그냥 수정된 파일만 짜잔 하고 공개하면 "Cracker"와 다를바 없기에(실은 cracker?!) 이번 삽질에 대한 내용을 글로서 언급 드릴려고 합니다.
*라이센스 등록없이 실행하는 부분에 대해서는 설명이 빠집니다. 이건 직접 언급하면 서로가 곤란하겠죠 ^.^
*당연히 전 Mappy 정식 등록 사용자 입니다.
*해상도 변경법을 소개 드리는 것입니다. M&Soft에서 해야 할 일을 사용자가 삽질 하고 있는 거죠.




수정버전
  Mappy v5.5.1 [2005-5-12 현재 최신 다운로드]

필요사항
  IDA Pro : Disassembler
  UltraEdit 등의 Hex editio
  Computer에 대한 여러 지식
  ARM instruction 지식 등등



M480x에서 맵피를 실행 해 보셨으면 아시겠지만 첫 intro 화면만 살짝 - 그것도 늘어진듯한 정상적이지 못한 image로 말이죠 - 보이다가 실제 지도 화면이 나오는 부분에서는 아무런 내용이 보이지 않습니다. 터치하면 동작은 하는데 말이죠.

그래서 고민을 했습니다.
왜! 그래픽 부분은 나오지 않고, bitmap 부분만 나오는 것이냐?

나름 vector 그래픽 처리 부분이데 엉망도 아니고 먹통이라는 것이죠. 그래서 이래저래 짱돌 돌리다 생각 난 것이... 240x320용으로 만들어진 맵피가 320x320에서는 먹통이라는 말은 240과 320의 차이에서 그 차이를 뒷감당 못하고 있다는 결론이 나왔습니다. [가로/세로는 대응 합니다 - 코드가 좀 답답하지만...]

그래서 해상도를 320x320이 아닌 강제로 240x320 혹은 320x240으로 인식 시키면 어떨까 생각 했습니다.
아! 당연히 멍충이 Mappy를 위해 RealVGA를 이용해서 96dpi 상태에서의 작업입니다. 기본인 128dpi는 기대도 하지 않았습니다(당연히 128dpi에서는 동작 안합니다)

자~ 아이디어는 나왔습니다. 멍충이에게 딱 어울리는 240x320 혹은 320x240으로 해상도를 고정시키자는 것이죠.
그런데 어떻게 고정 시킬것이가... 다시 고민이 밀려 옵니다.
분명 시스템의 해상도를 알아다가 이것을 기반으로 최초 화면을 구성한다는 것은 필수적인 과정이라 할 수 있습니다.

그래서 찾은 단서가 GetDeviceCaps 함수 입니다.
함수 원형은 아래와 같습니다.
GetDeviceCaps : This function retrieves information about the capabilities of a specified device.
int GetDeviceCaps( HDC hdc, int nIndex );
그리고 입력값을 살펴보면 (나머지는 생략)
  HORZRES       8     /* Horizontal width in pixels    */ 
  VERTRES       10    /* Vertical height in pixels      */

넵... 그렇군요 가로, 세로의 픽셀수를 가져올 수 있다는 것입니다.

그래서 GetDeviceCaps를 모두 찾아 보았습니다.
아래처럼 10개 미만으로 검색 되었네요
sub_49204+80
sub_49204+90
sub_CE1A0+4C  --> 수정의미 없는 코드임 (리턴값 사용 안함)
sub_CE1A0+58  --> 수정의미 없는 코드임 (리턴값 사용 안함)
sub_DA250+190 (DA3E0) --> CFrameWnd::OnCreate 호출 직후
sub_DA250+1A0
sub_DB498+2C  -------> 이놈이 진정 의미가 있고 / 나머지(설정값 사용 안함)는 의미 없을 듯
sub_DB498+3C
sub_22099C+180 --> CreateCompatibleDC 에 대한 BitPerPixel 확인 부분

냅 그렇습니다. 이정도면 무식하게 패치해서라도 충분히 테스트 할만 하다는 것이죠.
위 호출 부분에서의 코드는 아래 형태로 되어 있습니다.
BL      CreateDCW
CMP     R0, #0
BNE     loc_492A4
MOV     R1, #8          ; int
MOV     R0, #0          ; HDC
BL      GetDeviceCaps
MOV     R6, R0
MOV     R1, #0xA        ; int
MOV     R0, #0          ; HDC
BL      GetDeviceCaps
MOV     R5, R0
MOV     R0, #0          ; HDC
BL      DeleteDC
즉 GetDeviceCaps를 이용해서 가로,세로 픽셀을 받아오는 부분이 눈으로 확인이 됩니다.
그렇다면 이것을 직접 240x320 혹은 320x240으로 수정해야 하겠습니다.

GetDeviceCaps의 결과는 R0 로 넘어 옵니다. 그러므로 GetDeviceCaps 호출에 해당하는 BL 명령 대신 MOV 명령으로 바꾸어서 R0에 원하는 값을 대입 하도록 하면 되겠습니다.
즉 R0 에 240을 대입 하고 싶으면
MOV     R0, #0xF0   ==  F0 00 A0 E3

320을 대입 하고 싶으면 아래 처럼 구성 합니다. (ARM이 32bit로 명령하나가 완성되어 shift처리로 완성)
MOV     R0, #0x140  == 05 0D A0 E3
101(0x05) << 6(110b)  shift 부분===> 0D == 1011

자~ 이제 땜방 처리할 코드가 준비 되었습니다.
320x320을 인식 못하는 맵피를 위해 240x320 / 320x240 을 각각 준비 하면 아래와 같습니다.

보는법은 아래와 같습니다.
"차례"  "파일offset"
     [ 원본 hex code ]  --> [ 수정 hex code ]

240 x 320 설정용 patch data
1  0x038684
   [ F9 9C 07 EB ] --> [ F0 00 A0 E3 ]

2  0x038694
   [ F5 9C 07 EB ] --> [ 05 0D A0 E3 ]

3  0xC97E0
   [ A2 58 05 EB ] --> [ F0 00 A0 E3 ]

4  0xC97F0
   [ 9E 58 05 EB ] --> [ 05 0D A0 E3 ]

5  0xCA8C4
   [ 69 54 05 EB ] --> [ F0 00 A0 E3 ]

6  0xCA8D4
   [ 65 54 05 EB ] --> [ 05 0D A0 E3 ]

320 x 240 설정용 patch data      아래 부분만 수정하면 됩니다. 그러면 실행 성공 하게 되죠.
1  0x038684
   [ F9 9C 07 EB ] --> [ 05 0D A0 E3 ]

2  0x038694
   [ F5 9C 07 EB ] --> [ F0 00 A0 E3 ]

3  0xC97E0
   [ A2 58 05 EB ] --> [ 05 0D A0 E3 ]

4  0xC97F0
   [ 9E 58 05 EB ] --> [ F0 00 A0 E3 ]

5  0xCA8C4
   [ 69 54 05 EB ] --> [ 05 0D A0 E3 ]

6  0xCA8D4
   [ 65 54 05 EB ] --> [ F0 00 A0 E3 ]


자~ 위의 자료를 이용해서
Mappy.exe 파일로 부터 2개의 수정된 파일을 만듭니다 (Ultra edit값은 Hex 편집기 이용)
  Mappy_240x320_Fixed.exe
  Mappy_320x240_Fixed.exe

그리고 M480x에서 실행 해 봅니다.
실제 저는 240x320 만 먼저 실행 해 보고 - 급 좌절 해었죠... 한 2초 정도?!
그리고 320x240 버전을 언능(!) 만들어서 실행 했답니다.

결과!!!!!!!!!!!!!!
넵 320 x 240 강제 수정버전의 경우 지도 화면이 나왔습니다.
이 어찌나 기쁜 결과인가!! (물론 320x240 이므로 하단부분에는 배경 application이 보입니다 ㅎㅎ)


그리고 여기저기 다루어 보았습니다.
그런데 다른 문제가 있었습니다.

GPS 상태 버턴을 누르면 화면이 먹통이 되는 것입니다. 이 때 OK 버턴을 누르면 다시 지도 상태가 정상화 됩니다.
그런데 GPS 상태를 볼 수가 없다는 것이죠.
더구나 GPS가 인식이 되면(그냥 인식 잘 안됩니다 - GpsGate 프로그램을 사용 해야 합니다) 완전 먹통상태가 됩니다. Mappy를 강제로 죽여야 한다는 것이죠.


휴.... 한숨을 다시 쉬고 - 다시 생각 합니다 - 이번에는 무엇을 땜방 해 주어야 하는가....

다음 내용은 곧 다시 정리해서 post 하겠습니다.
[실제 위 내용 까지 정리 하고서, 몇주 뒤에 계속 해서 땜질 연구를 계속 했습니다]

----- TO BE CONTINUE~
다음글 보기



참고사진 추가~

M4800 실제 실행


에물레이터 실행 장면

+ Recent posts