으햐햐 ~(-_-)~ 겜브료 터레인~

Posted at 2009/02/21 17:16// Posted in gamedev
이틀동안의 삽질끝에
터레인을 지원하면서도 달랑 레이어 4장만 되는
겜브료 악랄한 기능을 수정해서 8장까지 확장했습니다.

첫날은 소스 백업안하고 진행하다가 잘못 건드리는 바람에 쉐이더 컴파일 에러로 실패-_-
둘째날은 전날의 실패를 교훈삼아 SVN 으로 등록한 다음 어제 수정한 코드를 하나씩 넣어가면서
작업한 끝에 ... 블렌드맵 설정에 아주 작은 실수로 인해 8시간 정도 디버깅(-_-) 노력을 제물삼아
드디어 기술적인 구현에 성공했습니다. >ㅁ< 꺄햐햐

겜브료측에서 1년이나 질질끌면서 수정을 안해주던 부분인지라..
뭔가 완전 꼬였나 생각했는데...; 놀랍게도(!) 거의 다 코딩이 되어있더군요 -_-
투자한 48시간에 비해 수정한 코드가 20줄 정도랄까요
(좀 허망한 생각이... orz; )

...

아마 제 생각으로
프로그래머는 다 작업해놓고 런칭하려는데~

QA 쪽에서 4 레이어 베이스+디테일+노말+패러럴 해서
텍스쳐 16장 혼합이  하드웨어 최소 조건이므로
8 레이어로 확장하게 되면 실행이 안될수도 있다.
그러므로 일단 4레이어로 가자 라는 식으로 막아놓은 듯 합니다.

이해가 안가는 것은
겜브료 자체가 노드 결합 쉐이더 생성 방식인지라...
게임 개발사가 엄한 짓만 안하면 문제가 없거든요 -_-)r
사실 노말맵 잘쓰기도 어려워 아예 제끼고 있는 상황인데 orz;;
그냥 주의해서 사용하라고 하지 TㅁT)

...

어쨌든 저 기술적인 구현을 작업자들도 쓸수있게하려면
오늘부터는 c# 의 세계에 빠져야 하는데-_-
하아...

python 쓰다가 c# 보니 뭐라 말이 안나오네요.
... (-- ); 문법도 지저분하고... 연동도 지저분하고... 코드도 지저분하고...

c# 에서 c++ DLL 디버깅이 안되서 고생했는데...
http://lohengrin.egloos.com/1787447 의 글을 보니
옵션/디버그/비관리 코드 디버깅을 체크해주면 작동하네요 ~(-_-)~


ps.
작년 12월에 자료실에 올라온거 보니 겜브료에 python 바인등을 하고 있는것 같드라구요
느무느무 좋은것 같아요 ㅋㅋ

불과 며칠전에 NiPointer - swig 연동하느라 고통받았던거만 빼면 말이죠 - _-)y- ~
이올린에 북마크하기(0) 이올린에 추천하기(0)
2009/02/21 17:16 2009/02/21 17:16
1. 프로세스 아이디 확인

$ ps -ux
USER        PID  %CPU %MEM     VSZ  RSS  TT  STAT  STARTED      TIME COMMAND
myevan  46674     0.0       0.2      39732  1784  pa- SL     10 507            84:27.05 ./game

2. gdb 실행파일 로드
$ gdb game
GNU gdb 5.2.1 (FreeBSD)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-unknown-freebsd"...
(gdb)

3. 프로세스 연결
(gdb) attach 46674
Attaching to program: home/myevan/game, process 46674
Reading symbols from /lib/libz.so.2...done.
Loaded symbols for /lib/libz.so.2
Reading symbols from /usr/lib/libstdc++.so.4...done.
Loaded symbols for /usr/lib/libstdc++.so.4
Reading symbols from /lib/libm.so.2...done.
Loaded symbols for /lib/libm.so.2
Reading symbols from /usr/lib/libc_r.so.5...done.
Loaded symbols for /usr/lib/libc_r.so.5
Reading symbols from /lib/libc.so.5...done.
Loaded symbols for /lib/libc.so.5
Reading symbols from /libexec/ld-elf.so.1...done.
Loaded symbols for /libexec/ld-elf.so.1
[Switching to Process 68794, Thread 1]
0x283a32af in poll () from /lib/libc.so.5
(gdb)

4. 브레이크 포인트 설정
(gdb) b do_skillup
Breakpoint 1 at 0x8111419: file cmd_general.cpp, line 791.

5. c++ 멤버 함수 브레이크 포인트 설정
(gdb) rbreak CHARACTER::SkillLevelUp
Breakpoint 2 at 0x80c91f2: file char_skill.cpp, line 576.
void CHARACTER::SkillLevelUp(unsigned long, unsigned char);

6. 브레이크 포인트 리스트 보기
(gdb) info b
Num Type           Disp Enb Address    What
1   breakpoint     keep y   0x08111419 in do_skillup(CHARACTER*, char*, int, int) at cmd_general.cpp:791
2   breakpoint     keep y   0x080c91f2 in CHARACTER::SkillLevelUp(unsigned long, unsigned char) at char_skill.cpp:576

7. 브레이크 포인트 제거
(gdb) delete 1
(gdb) info b
Num Type           Disp Enb Address    What
2   breakpoint     keep y   0x080c91f2 in CHARACTER::SkillLevelUp(unsigned long, unsigned char) at char_skill.cpp:576

8. 디버깅 시작
(gdb) c
Continuing.

9. 프롬프트 모드로
^C
Program received signal SIGINT, Interrupt.
0x283a32af in poll () from /lib/libc.so.5
(gdb)

10. 프로세스 연결 해제
(gdb) detach
Detaching from program: home/myevan/game, Process 46674, Thread 0
(gdb) quit
$

관련링크:
KLDP GDB 잘 쓰기
GDB 를 이용한 디버깅
이올린에 북마크하기(0) 이올린에 추천하기(0)
2007/05/31 17:18 2007/05/31 17:18
import sys
import ctypes

class DbgOut:
    def write(self, msg):
        conout.write(msg)
        trace(msg)

trace       = ctypes.windll.kernel32.OutputDebugStringA

dbgout      = DbgOut()
conout      = sys.stdout
conerr      = sys.stderr
sys.stdout  = dbgout
sys.stderr  = dbgout

if "__main__" == __name__:
    print "debug message test"


이올린에 북마크하기(0) 이올린에 추천하기(0)
2007/05/30 15:06 2007/05/30 15:06
class Obj:
    def __init__(self):
        print "new obj"
    def __del__(self):
        print "del obj"

class Test:
    def __del__(self):
        print "del test"

    def Run(self):
        o = Obj()

        # syntax error
        akgjal

def Sub(test):
    try:
        test.Run()
    except:
        pass

    print "end Sub"

def Main():
    test = Test()
    Sub(test)
    print "end Main"

Main()
print "done"

위의 코드를 실행시키면 Test.Run 함수에서 문법에러가 발생하면서
Sub 함수의 try-except 에 걸리게 됩니다. 문제는 Test.Run 함수에 있는
o = Obj() 로 생성한 변수가 언제 제거되냐입니다.

그냥 생각하기에는 Test.Run 을 빠져나올때 제거가 되지 않을까 했는데...


C:\WINDOWS\system32\cmd.exe /c test.py
new obj
end Sub
del obj
end Main
del test
done
Hit any key to close this window...

한단계 위쪽인 Sub 함수를 빠져나올때 제거가 되더군요.

-_-)> 일단 실험 결과는 이렇고...; 좀더 문서를 찾아봐야할듯합니다.
이올린에 북마크하기(0) 이올린에 추천하기(0)
2007/05/30 11:18 2007/05/30 11:18
독일에서 3일전에 편지가 왔다-_-

This happens sometimes during normal gaming.

This happens ALWAYS in the following situations:

- when starting the client for the first time after logging-in

- when starting the client immediately again (the second time): after selecting empire

- next time after creating the character

(= so at the beginning, the client finishes himself off 3 times, and only with the 4th attempt, the player can really access the game)

This also happens ALWAYS in the following situations:

          - when keying in wrong login-data in login-window

          - when trying to go to login-window from in-game

         -  when trying to go to character selection window from in-game


ALWAYS 의 압박 orz;;

독일버전은 잘 실행되는데 이탈리어 버전에서만
로그인후 캐릭터 선택화면에서 게임 실행될때, 혹은 로그아웃 후 캐릭터 선택할때만
클라이언트가 죽는다는 것이었다.

하지만 한국어 윈도우에서는 문제가 없었다 (-_-); 그렇게 하루가 흘러가고...

영문 윈도우를 설치해 실행해보았지만 이상무;
이탈리어어로 설정해도 마찬가지였다.

결국 영문 윈도우에서 AppLocale 을 설치하고, 현재 지역 위치도 이탈리아로 설정하자
겨우 에러 상황을 재현해낼 수 있었다. 한번 에러가 발생하니 AppLocale 이 없어도
에러가 항상 발생하는 행운까지 GET! -_-)!

하지만 회사 개발 컴파일러인 vc 6.0 디버그 버전에서는 에러가 나지 않는 절망의 상황 T_T);
( 게임 컴파일은 꽁짜 컴파일러 visual c++ .net 2003 toolkit 를 사용중이라 IDE 디버깅 불가 )

결국 원점으로 돌아와 -_-
릴리즈 버전 에러 리포팅 정보를 분석하기 시작했다.

Exception Type: 0xc0000005

eax: 0x0012caa8 ebx: 0x0012caa4
ecx: 0x00181a9b edx: 0x00617475
esi: 0x1c6e3000 edi: 0x34ef0a28
ebp: 0x0012c3bc esp: 0x0012c3b0

0x00403fc4  game - std::string.assign
0x0044c277  game - LoadSkillDesc
0x0046c60b  game - LoadLocaleData
0x0046f741  game
0x1e04cf4c  python22.dll
0x8d0c4d8b

흠 (-_-); std::string assign 이 에러날리는 없으므로 스킬 데이터를 로딩하다가
메모리가 깨진 현상인건 틀림없다. 지난번에 수정한 lower 함수 부분일까도 의심해봤지만
해당 코드에서는 사용되고 있지 않았다.

에러나는 라인이나 로그로 찍어보자

라고 코딩해보니 -_-); 에러 위치는 마지막 라인...
게다가 알수없는 스킬 번호라는 문구까지 보이는게 아닌가

코드를 다시 살펴보니 흑흑

for (int linePos = 0; linePos != lineCount; ++linePos)
{
     if (!SplitLines(lines[linePos], &tokenVector))
        continue;
 
     vnum = atoi(tokenVector[SKILLDESC_VNUM]);

     ... 어쩌구 ...

     tokenVector[SKILLDESC_VAL] 저쩌구 ..
    
}

이런식으로 되어있는걸 발견 (-_-);

vector 각 요소에 접근하는데, 최대 길이 체크도 안하고 과감하게 직접 접근하는 코드들이
대범하게 나열되어있는것이 아닌가 T_T);

일단은 각 요소가 일정개수 이하일때는 공백라인으로 에러 로그 남기고 건너뛰도록
응급조치 종료 _ -_)~

-----------------------------------------

텍스트 파일을 파싱할때는 아래 체크 과정을 거치는 것이 좋다

for line in lines:
    line = line.strip()
    if not line: # 공백 라인 체크
        continue
    tokens = line.split("\t")
    if len(tokens) < TOKEN_COUNT: # 토큰 개수 체크
        continue

    tokens[pos] # 접근




이올린에 북마크하기(0) 이올린에 추천하기(0)
2007/05/09 17:46 2007/05/09 17:46

visual c++ 리모트 디버깅

Posted at 2007/05/09 16:28// Posted in msvc
www.kgda.or.kr/cgi/technote/ read.cgi?board=program02&y_number=297

대상 컴퓨터 작업
0. 첨부 파일 다운로드

리모트 디버깅


1. 첨부된 파일 실행 파일을 실행한다.
2. Setting을 눌러 소스 컴퓨터의 주소를 적는다
3. Connect 버튼을 누르고 대기한다

소스 컴퓨터 작업
1. Build->Debugger Remote Connection 실행
2. Network(TCP/IP)를 선택하고 Settings 를 눌러 대상 컴퓨터 주소를 적는다.
3. Project Setting 에서
Working Directory에는 대상 컴퓨터에서 실행될 폴더 주소를
Remote excutable path and filename: 에 대상 컴퓨터에서 실행될 파일의
전체경로(디스크이름을 포함한..)를 적는다
4. 컴파일
5. 파일을 대상 컴퓨터에 복사한다
6. 실행

http://www.myevan.net/phpBB/viewtopic.php?t=1929&highlight=remote


안녕하세요. 매크로 없는 메비~랍니다.

리모트 디버깅 팁 몇가지를 적어봅니다.

일단 파일을 다운로드 할 필요없이 VC++이 깔린 PC에서 다음 파일들을 복사해서 한 폴더에 넣고 사용하비면 됩니다. Help 문서에서도 찾을 수 있지만 간혹 버젼이 틀리거나 하면 낭패이므로 참고하기 바랍니다.

DM.DLL
MSDIS110.DLL
MSVCMON.EXE
MSVCP60.DLL
MSVCRT.DLL
PSAPI.DLL
TLN0T.DLL

디버깅을 할때 실행 폴더와 실행파일 경로등이 항상 문제가 됩니다. 빌드한 실행파일의 timestamp 등을 체크하기 때문에 버젼이 틀리면 경고를 해주면 여로모로 귀찮습니다. 특히 리모트 파일의 실행 폴더가 로컬 파일과 같은 주소로 사용되기 때문에 로컬에서 쓰다가 리모트에서 쓰고 왔다갔다 하려면 프로젝트 셋팅을 매번 바꿔줘야 하는 경우가 있습니다.

이럴때는 두가지 방법이 있는데 다음과 같습니다.

1) 리모트 머신도 로컬과 동일한 폴더/드라이브명을 갖게 한다.

동일한 폴더 셋팅은 프로젝트의 Post-Process 에 간단한 copy 명령등을 추가해서 리모트 머신의 특정 폴더에 빌드가 끝난 exe 파일과 pdb 파일들을 자동적으로 복사하게 해주는 것입니다. 이는 매번 컴파일이 끝날때마다 자동적으로 이뤄지고 리모트 컴퓨터에 공유폴더만 정상적으로 작동하면 언제나 사용할 수 있십니다.

2) 동일한 공유 폴더를 이용한다.

먼저 작업할 폴더를 공유폴더로 설정합니다. 그리고 해당 공유 폴더를 특정 드라이브에 맵핑합니다. 가령 \\kwonil\TestCode 란 폴더가 공유되어 있으면 x: 드라이브에 \\kwonil\TestCode를 공유시킵니다. 그리고 VC++에서 작업을 할때는 모든 작업이 x: 드라이브에서 작업할 수 있게 해둡니다. 보통 프로젝트 폴더를 공유하지 않고 워킹 폴더(게임 폴더)를 공유해놓고 빌드되는 실행파일의 타겟 경로를 게임 폴더로 해놓는 것도 좋은 방법이죠. 그리고 다음 작업은 리모트 머신에서 같은 드라이브 즉 x: 드라이브에 \\kwonil\TestCode를 공유해주는 것이죠. 그러면 리모트 머신도 로컬 머신도 동일한 경로(x:)에서 모든 것이 돌아가기 때문에 모든 작업이 깔끔하게 끝납니다.

개인적으로 1)을 선호했는데 뭣보다 안정적이고 공유폴더보다 속도가 좋기 때문이죠. 이것저것 자료가 자주 바뀌거나 로컬과 리모트에서 공유를 열어줘야할 필요가 꼭 있을때는 2)도 좋지만 저는 1)을 써서 계속 작업을 했었습니다. 매번 손으로 복사해주는거 매우 불편하니까 Post-Process에 한줄만 추가해주면 되죠. copy~~ 명령으로 말이죠. ^_^ 리모트 디버깅은 풀스크린 모드로 작업할때, 특정 환경을 구축해서 테스트할때 매우매우매우 우용하다고 생각합니다. 저는 로컬라이즈 작업을 처음부터 저렇게 해왔고 리모트 머신에 OS를 여러개 Ghost 이미지로 만들어서 매번 바꿔가면서 리모트 디버깅으로 작업을 하곤 했었죠. 그래서 하루에 OS 10개를 사용한(언어, 버젼별) 테스트도 가능했습니다. ^_^
이올린에 북마크하기(0) 이올린에 추천하기(0)
2007/05/09 16:28 2007/05/09 16:28