앞의 내용은 게임 파크 개발자 게시판에 적었던 내용입니다
1. _assert 를 활용
따로 assert 문이 없는 관계로 assert 문을 만들어서 사용 했는데, 디버깅할 때 도움이 많이 되었습니다.
#if GP_DBG == 1 extern void _assert(void *, void *, unsigned); #define ASSERT(A) { if (!(A)) _assert( #A, __FILE__, __LINE__); } #else #define ASSERT(A) #endif
|
로 해서 선언하고, 아래처럼
void _assert(void * exp, void * filename, unsigned line) { GP_PALETTEENTRY tmp_entry[256]; GPDRAWSURFACE * cur; char text[128]; int key;
cur = ...; // backsurface
GpRectFill(NULL, cur, 0, 0, 320, 240, 0x01); GpTextOut(NULL, cur, 10, 16, "Assertion Failed!", 0); sprintf(text, "File: %s", strrchr(filename, '')+1); GpTextOut(NULL, cur, 10, 32, text, 0);
sprintf(text, "Line: %d", line); GpTextOut(NULL, cur, 10, 48, text, 0);
sprintf(text, "Expression: %s", exp); GpTextOut(NULL, cur, 10, 64, text, 0);
memset(tmp_entry, 0, sizeof(tmp_entry)); tmp_entry[0] = 0; tmp_entry[1] = 0xfffe; GpPaletteEntryChange(0, 256, tmp_entry, GPC_PAL_ASYNC_REALIZE);
do { GpKeyGetEx(&key); } while(!(key&GPC_VK_START)) ;
// redo palette }
|
정의해서 게임 중에 assert 나오면 화면에 표시하게 하고, start 누르면 계속 진행하도록 하면 체크가 가능하겠네요.
PC 상에서와 약간 다르게 동작해서 문제가 생길 수 있으니...
GP32 실행 중에 assert 가 뜨면 do while 문에서 start 누를 때까지 프로세스가 머물기 때문에 바로 그 부분에 디버깅 들어가면 assert 나는 상황을 쉽게 체크 해볼 수 있죠.
2. __packed 사용
구조체에서 align 안된 형태로 억세스하려고 할 때는 struct 앞에 __packed 를 붙여주면 됩니다.
예를 들어 PC에서 아래처럼 구현한 것이라면
#prama pack(push, tt) #prama pack(1) typedef __packed struct { unsigned short BitsPerSample; } WAVE_Pcm; #prama pack(pop, tt)
|
는
typedef __packed struct { unsigned short BitsPerSample; } WAVE_Pcm;
|
식으로 할 수 있겠네요.
3. 추가 : 재미로 읽는 개발 후기
개발자 SDK 가 공개된 이후에는 어떤 식으로 접근하는 지 알 수 없지만 제가 개발할 때는 완전히 윈도우로 개발을 하고, 이와 병렬로 GP32에서 실행되도록 코드를 수정하고 디버깅 했습니다. (제가 작업한건 후자의 작업이었고, 게임이 거의 진행되어 가는 시점에 투입되었습니다.)
거의 전처리기를 이용해서 최소한의 코드만 수정해서 완전히 같은 버전이 나오도록 작업했습니다. (요새는 같은 기능의 윈도우용 API로 작업하고 GP32로 포팅 하는 거 같으니, 제가 했던 분야의 작업을 게임 파크 쪽에서 제공해주는 거라고도 할 수 있겠네요. )
Gp32로 리모트로 디버깅하는 것은 pc로 하는 것보다 훨씬 불편하고 어렵기 때문에 – 그 비싼 Multi-ICE 장비를 사용해도... - 가능하면 게임 로직은 pc 상에서 완벽하게 돌아간다고 가정하고 작업을 했습니다. 다행히 어스토의 경우 프로그래머 분들이 잘해주셔서 별 다른 개발상의 문제 없이 출시 될 수 있었습니다. 제가 내린 결론은 게임 로직은 디버깅이 용이한 PC 상에서 해결하는 것이 오히려 개발 기간을 단축시킨다는 것이었습니다. (비슷한 이유로 PS2 역시 끔찍할 것으로... )
GP32에 최적화 하기 위해서 RLE 도 세로 방향으로 엔코딩 했는데, 실제로 PC상에서는 개발이 진행된 상태라 개발 중인 PC 버전에 아예 가로로 엔코딩 하는 루틴을 넣어버렸습니다. (PC상에선 PC의 메모리 방식을 그대로 사용)
색감의 경우 PC랑 많이 틀려서 별도의 파렛을 분리해서 작업을 했습니다. (프로그래머 입장에선 별 일 아니었지만, 디자이너 분은 고생을... T_T)
실제 메모리 문제와는 별개로 저장된 게임 파일 크기 때문에도 여러 가지 문제가 있었습니다. 기본적으로 모든 파일은 LZ77 압축을 했고, 압축이 용이하도록 일부 파일은 4개로 쪼개서 재 정렬해서 저장했습니다.
오프셋을 4로 나눠서 나머지가 0, 1, 2, 3인 것들로 나누었는데, 실제로 4바이트 데이터의 경우 상위가 동일한 경우가 많아서 압축 율을 훨씬 높일 수 있었습니다. (특히 스크립트 바이너리 파일이나 수치 데이터 베이스 파일, 맵데이타등등...)
그리고 중복되는 데이터, 불필요한 데이터, 예전 데이터는 작업자와 함께 하나하나 체크해서 삭제했습니다. 사운드 이펙트는 모두 ADPCM 방식으로 압축했고, 약간 거슬리는 효과음에 대해서만 그냥 PCM 방식을 사용했습니다.
원래 목표했던 16메가에 맞추기 위해 눈물 나는 노력을 해야만 했습니다. 특히나 막판에 그래픽 리소스가 자꾸 추가 되어서 겨우 맞춘 한계 치를 조금씩 초과하게 되는 일이... 결국엔 리드 프로그래머 분이 디자이너분 모셔놓고 지워도 될 파일과 프레임을 정하는 안타까운 일도 있었죠. (아마 지금도 당시 매일 리포트 하던 용량 상황 보면 치열함을 느낄 수 있을 지도... 디자이너 분들은 자꾸 넣고 싶어 하시고, 저나 프로그래머 분들은 두려워 하시고, 그래도 몰래 몰래 추가되는 리소스를 찾아 검증하는 것이 꼭 숨바꼭질 같았다고 할 수 있었습니다.) 사운드 이펙트 역시도... 프로그래밍적으로 더욱 확보할 수 없었던 것이 죄송스러웠다는.. . (이 과정에서 오프닝 보컬곡도 편집되었던 것으로 기억되네요. T_T)
하지만 막판에 게임을 미디어를 32 메가를 사용하기로 결정되어서, 추가된 음악 스트림 파일이 14메가 정도가 되어서 약 2M 정도의 메모리를 추가로 확보할 수 있어서 후에는 큰 문제가 없었습니다. (이 2M가 한 200메가는 되는 거 같더군요.)
결국엔 개발 버전에선 리소스가 50메가 정도였고, GP32 용으로 엔코딩 된 버전은 약 16메가 정도가 되었습니다. (음악을 제외하고...)
GP32 의 초기 버전의 미디 기능이 최종 출시 버전에서 빠져서 음악 역시 만만치 않은 큰 문제가 되었습니다. (역시 문제는 용량이죠.) 처음에는 원작의 ROL 파일을 이용해서 FM 사운드를 웨이브로 변환하면서 플레이 하도록 처리 했는데, 속도상의 문제로 심하게 갈등 하다가, 결국에는 전곡을 웨이브 파일을 사용하게 되었습니다. 음악도 수십곡 (40곡도 넘었던걸로 기억되네요.) 되다 보니 음악을 편집하는 것도 한계가 있었고, 결국엔 안타깝게도 퀄리티를 낮출 수 밖에 없었습니다. (아마 실제로 GP32를 게임 개발해보신 분들은 한번쯤은 심각하게 고민하셨을 듯합니다.)
GP32가 게임에 맞는 최적화 / 메모리 / 용량이 PC 보다도 훨씬 타이트 하지만 나름대로 매력 있는 플렛폼입니다. (아마 다른 게임기 역시 비슷하지 않을 까 합니다.) 지금 개발하시는 분들은 PC로만 개발하는 것에서는 얻기 힘든 것을 얻을 수도 있는 최대한 많이 얻으시길...
ps. 거의 일년이 되어가는 시점이다 보니 사실 기억은 가물 가물 합니다 T_T
댓글을 달아 주세요
너는 차가운 위치를 만들었다!