갑자기 패미컴 프로그래밍이 땡겨서.. 급번역질...
근데 난 C를 모른다란게.. 문제... 이를 어쩐다... 까이꺼 하면서 공부할까... ㅡㅡ;;
NES Game Programming Part 1a series by WolfCoder (January 2010)
안녕! 콘솔 게임 프로그래밍 안내서 시리즈를 집필한다는 건 재미있다. 물론 옛날 텍스트 기반 게임들이 아닌, NES나 게임보이 어드밴스 같은 가정용 게임기를 말하는 거다. 이 시리즈들은 고전적인 패미컴에 대부분을 작업하면서, PC나 다른 콘솔들에 대한 몇가지 섹션도 포함시킬 것이다. 이해하려면 C에대한 몇가지 기초 지식이 있어야 하지만, 효율을 더 올리기 원한다면 몇몇 플랫폼들에 기반한 ASM에서 삽질을 할 수도 있다. 사전에 준비해야 할 것들을 일러주겠다.
- C에 대해 상기하고 공부해라. 나는 C 프로그래머들의 실무적 교과서인 K&R book를 추천한다.
- 프로그램 코드를 수정하려면 편집가 필요하겠지만, 이 파일들은 하나하나 마이크로소프트 비주얼 스튜디오에서 구문 하이라이팅 같은 효과를 내며 열 수 있다. 혹은 우리가 사용할 툴 연계 작업이 깔끔하게 되는 Programmer's Notepad 도 있다.
-우리는 그림파일들을 작동 시킬 것이다.. 어도브 포토샵은 필요하지 않으니, 간단한 이미지나 픽셀-아트만 준비하라. 편한 설정을 원한다면 GIMP 또는 Paint.net를 사용해보라. 하지만 그림판 사용은 강력히 말리는 바이다.
- 연주를 할 수 없다면, (MIDI 같은) 음악 파일들을 재생하는 좋은 방법은 트리톤 XM 같은 읽기 쉬운 형식으로 변환하는 것이다. MODPlug Tracker는 MIDI에서 XM이나 그 밖의 형식으로 변환해주는 훌륭한 프로그램이다. MOD 파일들은 WAVE나 MIDI 교환하며 사용할 수 있다. 어쨌든 음악에 대해서 꽤 어려울 거라고 많이 걱정하지 말자. 난 대부분의 독자들이 극복하리라 생각한다.
Introduction to the NES
Classic
내가 현재까지 만들어진 것 중 가장 혁신적인 콘솔에 대해서 소개 했던가? 콘솔중의 하나로 오늘날 콘솔들이 만들어지게 정의한 것이다. 카트리지는 완성도가 높았고, 컨트롤러들은 딸려서 달려있고, 비디오와 전원을 위한 간단한 스위치가 있었고, 콘솔 자체는 아주 튼튼한, (80년대에) 인상적인 하드웨어를 가졌다. 또한 도서관을 가득채울 수 있는 거대한 양의 NES 게임 라이브러리들이 있다! 믿을 수 있는가? 이 비디오(this video)를 보라. 이제 닌텐도에 대해 말하고 싶은 건, 하지만 그 멋진 회색의 상자는 시장을 정말 휘어잡았지.
누군가가 NES와 게임들에 대한 이야기를 하는 것을 보고 싶다면, Angry Video Game Nerd 를 보라. 그의 비디오들은 NES 게임들의 나쁜점과 하지 말라고 설명하는 형식의 분노하는 코미디를 하는데 이 자습서 시리즈의 훌륭한 동반자가 될 것이다. 그러나, 지금은 NES의 안쪽에 무엇이 들었지를 이야기 한다.
NES는 코모도어64나 아타리에 등에 들어있는6502 CPU의 변형된 버전을 포함한다. ~1.79Mhz 클럭으로 동작하며, 물론, 8-비트이다. 또한 PPU(그림 처리 유닛 Picture Processing Unit)로 알려진 이상한 비디오 카드를 가지고 있다. 유닛은 배경과 64 입자 스프라이트들을 지원하고(8x8 또는 8x16 pixels), 4개의 배경과 4개의 스프라이트 파레트들, 하나의 64-색 마스터 NTSC 파레트, 그리고... 가 대략이다. 화면은 256과 240 픽셀로 큰편이지만 NTSC 표준이 더 작기에 위와 아래가 약간 잘려진다. 음향을 위해선, 2개의 4채널 파형(square waves), 하나의 3채널 파형(a triangle wave), 하나의 노이즈 파형과 그 밖의 다른 원시 음향 채널들을 가진다. 아 참, 2개의 컨트롤러 포트들이 있다. 우리가 표준 게임들을 만들기 전에는 모든 이국적이며 일본적인 하드웨어를 찾을 일은 없을 것이다.
The 6502
Something like this thing, right here
6502는 원시적인 프로세서다. 많은 연산을 하지 않기에 8비트 이상의 연산을 하려면 몇 가지 지침들을 하나하나 해야 한다. 덧셈, 뺄셈, 논리연산, 그리고 8비트 숫자들의 비트 시프트들을 언제 어디서나 할 수 있는 일반적인 규칙이이다. C 프로그래밍의 다른 기능들은 정말 천천히 할 수 있다.
The Compiler
Pretty simple
이제 중요한 부분이다. 우리는 CC65라 불리우는 컴파일러로 작업할 것이다. NES를 포함한 6502로 구현된 많은 장치들을 위한 어플리케이션을 개발하는 라이브러리들을 포함하고 있다. 최신 버전은 여기서(from here) 내려 받을 수 있다. 또한 컴파일러 자체가 들어있는 다른 다운로드 경로로 받아야 하는 NES 라이브러리들이 필요하다.
이제, 컴파일러 환경 설정을 하자. 당신은 이 두 개의 파일들을 내려 받아서 (윈도우를 사용한다면) 압축을 풀 준비를 하자:
Downloads folder
우선, 디렉토리에 컴파일러의 압축을 풀고, NES 라이브러리들을 같은 디렉토리에 넣는다. 컴파일러 먼저 압축을 풀고 NES 라이브러리들 다음에 넣는 것은 매우 중요하다. 아마 다음처럼 되었을 것이다:
Installed directory
이제 “bin” 디렉토리로 가면 다음과 같이 보일 것이다:
현재 디렉토리의 위치를 명심하라. 이 디렉토리를 환경 변수에서 가리키게 할 것이다. 당신의 운영체제에 따라 다르겠지만, 어떤 디렉토리에서도 터미널 창(명령어 창)에서 cl65 형식을 참조할 수 있게 하는 것이 최종 목표이다. Vista에선, “내 컴퓨터”에서 우 클릭을 하면 나오는 , 속성에서, 고급 탭의 환경 변수 설정을 클릭하라. “Path” 변수를 수정하여 이 exe파일들의 경로를 추가하고 ; 을 끝에 써 줘라. 이 단계를 정확하게 했다면, cmd를 실행하고 cc65라고 치면 입력 파일이 없다고 나올 것이다. 안 된다면, 당신의 윈도우 버전에선 환경 변수들을 어떻게 변경해야 하는지 찾아보라. 만약 당신이 그다지 똑똑하지 않고 지저분한 방식을 사용하길 원한다면, 이 파일들을 그냥 C:\WINDOWS\ 아래의 system32 폴더에 복사해 넣어라. 이 설정은 지저분하고 위험요소가 있으므로, 변수 설정을 강력히 추천한다.
What you should see in the console
The Libraries
물론, 이것이 컴파일러를 입력 창에서 구동하게 하는 것이 귀찮고 성가시지만, 조금만 더 기다려. 우리는 이제 "Hello, world!" 프로그램을 실행할 것이니까~ 좋아, 당신은 몇 개의 기본 폴더(나는C:\NES\)를 만들고 앞서 만든 cc65가 설치된 디렉토리에서 lib와 딸린 폴더들을 복사해와라. 이제 다음과 같은 폴더가 생성될 것이다:
Full view of my window
내가 사용한 경로는 위와 같다. 이 지침서에서는 모든 프로그램들을 컴파일 할 때 같은 경로를 사용하므로 같은 경로로 설정하는 것을 추천한다.
Programming
휴… 이제야 우리의 "Hello, world!"를 테스트 프로그램에 쓸 준비가 되었는데, 여전히 잘 따라오고 있나? 정말? 좋아, 이번에는, 프로그램 코드가 들어갈 폴더를 만들자. 폰트와 모든 것들이 들어간 실제 그림파일들이 포함된 화면에서 보여지는 텍스트를 얻는 방법은 여러가지가 있지만, 고맙게도 cc65로 만들어진 모든 게임은 코모도어 64 기본 그래픽인 VROM의 두 개의 뱅크에 들어 있기에 시작하자 마자 바로 텍스트를 그릴 수 있다. VROM은 몇몇 그림 데이터가 들어있는 프로그램의 일부이다. 다음 프로그램을 당신이 방금 만든 폴더에 c 파일로 저장하라.
/* Hello, NES! writes "Hello, NES!" to the screen written by WolfCoder (2010) */ /* Includes */ #include <nes.h> /* 화면에 문자 쓰기 */ /* NES 하드웨어가 우리가 지정해준 화면으로 자동적으로 스스로 위치를 변경하는 방법을 살펴보라 */ void write_string(char *str) { /* 커서의 위치 */ /* 이건 한번만 필요하다 */ /* 이것은 화면의 위에서부터 첫 8픽셀까지는 숨겨져 있기에 2칸(cell) */ *((unsigned char*) 0x2006) = 0x20; *((unsigned char*) 0x2006) = 0x41; /* 문자 쓰기 */ while (*str) { /* 글자 쓰기*/ /* 컴파일러는 그래픽에서 ASCII와 일치하는 셋을 집어 넣는다 */ *((unsigned char*) 0x2007) = *str; /* 문자를 읽는 포인터 진행 */ str++; } } /* 프로그램 진입점 */ int main() { /* VBLANK를 기다리지 않으면 PPU를 사용할 수가 없다 */ waitvblank(); /* nes.h 안에 있다*/ /* 정말 이상한 방법으로 색상을 지정하지 않나? */ /* 우선 배경색을 지정해야 한다 */ *((unsigned char*) 0x2006) = 0x3F; *((unsigned char*) 0x2006) = 0x00; *((unsigned char*) 0x2007) = 1; /* 그 다음은, 글자 색을 지정해야 한다 */ *((unsigned char*) 0x2006) = 0x3F; *((unsigned char*) 0x2006) = 0x03; *((unsigned char*) 0x2007) = 0x30; /* 화면으로 보낼 메시지를 기록한다 */ write_string("Hello, NES!"); /* 화면 위치 설정*/ /* 앞의 것은 X offset 값이고 두번째는 Y offset 값이다 */ *((unsigned char*) 0x2005) = 0x00; *((unsigned char*) 0x2005) = 0x00; /* 화면 사용 가능 설정 */ /* 기본적으로, 화면과 스프라이트 기능은 꺼져있다 */ *((unsigned char*) 0x2001) = 8; /* 대기*/ /* 컴파일러는 main 함수를 계속해서 돌것으로 예상되므로, 여기서 일단 보류하자*/ while (1); return 0; } |
이제 이것을 컴파일 하는 대신에, 배치 파일을 하나 만들자. 배치 파일들은 멍청한 짓이지만, 나는 레드햇 리눅스 배포본이 없고 CC65의 리눅스 버전을 내 리눅스 머신에 설치하기 위해 몇몇 RPM 인스톨러들이 설치되는게 싫어서... 좋아, 좋아, 이 경우에는, 난 당신이 윈도우와 최소한은 비슷하다고 가정할 거다. 사실, 만들어야 하는 배치 파일은 정말 쉽다. 한번 봐라:
1
|
@echo off
| |
2
|
cl65 -L C:\NES\lib -t nes
-I C:\NES\include *.c -o hello.nes
|
3
|
pause
|
해봐라. 그것뿐. 다른 두 줄은 윈도우를 초기화 하고 오류/경고의 경우를 열어놓는다. 좋지 않은 무수한 지침서들을 봐 왔지만, 실제로 이 모든 명령을 설명해 주는 것이다..
-L [경로] : 이것은 입력한 경로에서 .lib 라이브러리 파일들을 읽어온다. 이것은 nes.lib가 있는 위치이자 앞서 우리가 C:\NES\lib에 파일들을 복사 해 놓은 경로이다.
-t nes : 이제 우리는 라이브러리들을 참고 할 수 있고, 이 명령은 컴파일러에게 NES 게임을 만든다고 일러주는 것이다. nes.lib와 모든 필요한 것들을 연결시켜준다.
-I [경로] : 이것은 우리가 포함시킬 .h 파일을 참조하는 경로이다. 앞서 우리가 복사한 경로는 두 개의 함수가 포함된 nes.h가 들어 있다! 멋진 “VBlank를 기다리는 것”을 갖는 것은 중요하기에, 불평하지 마라.
*.c : 간단하게, 이것은 .c로 끝나는 이름의 모든 파일들을 컴파일 하라는 것이다.
-o hello.nes : 이것은 출력 파일의 이름이다.
위의 파일은 .bat 확장자를 가진다. 이것들은 프로그램처럼 동작한다. 만들어 놓은 .c 파일들에 넣어놓고 더블클릭으로 실행하면 마술을 부릴 것이다. 아무 키나 누르라는 확인 메시지가 나오면 컴파일러가 문제없이 작동한 것이다. 출력물은 .nes 파일이다! 쉽지 않나? 흠… 항상 그런 건 아니지만. 만약에 문제들이 발생한다면, 윈도우 배치 파일 동작 방법(Windows Batch files work)을 살펴보길 강력히 권한다. 내 말은, 윈도우의 파일 시스템과 씨름하는건 NES 게임들을 만드는 거보다 나은 건 없다.
Run Program
좋아, 그러면 나아가 방금 만든 프로그램을 동작시키자. 잠깐, 어떻게 하는지는 아는건가? 물론, 이 프로그램들은 에뮬레이터로 테스트를 할 수 있다. FCEUX는 게임 개발자를 위한 완벽한 에뮬레이터이다. 역어셈블러인 PPU 뷰어나, Name 테이블 뷰어 그리고 그 밖에 기능들이 들어있다. 우리는 게임을 만들려는 거지, 하려는게 아니므로, 지금은 나에게 ROM을 요구하지 말라. 머… NES에서 좋아하는 게임 몇 개 정도는 해보라. 원래 기계가 있다면, 박살내지는 마라. 동작하지 않는다면, 스스로 ROM들을 찾아봐라. 걱정마라, 합법적으로 하고 싶으면, 소유하고 있는 게임에서 이미지를 추출하면 된다. 에뮬레이터 자체는 합법이지만, 어떤 BIOS 코드 또는 실제 NES의 어떤 것도 포함할 수 없고 사용할 수도 없다고 알려져 있다. 이 작업에 흥미를 가지고 읽어 본다면, NES는 실제로 불법 복제나 써드파티들이 게임을 만드는 속임수 들에 관한 재미있는 역사를 가지고 있다.
이제, .nes 파일을 열어보면 다음과 같이 될 것이다:
Classic test program output
재미있다. 당신은 정말, 정말 이상하게도 기계에 바로 작동하게 프로그램을 하지 않은 것에 대해서 수많은 궁금증이 생겼을 것이다.
프로그램은 보기 쉽게 배치와 코멘트들을 달아줘야 한다. 위의 hello world 프로그램에 대해 차근차근 설명해 보겠다:
우선, 분명히, NES 게임에는 입력이 필요가 없다. 우리는 단지 정수(int)와 약간 많은 값들을 반환하는 주요 함수만 있으면 된다.
어떤 결과를 얻기 위해선, 메모리에 직접적으로 값들을 써야 한다. 이런 것들은 숫자들을 형 변환(casting)하여 포인터들에 넣는 것과, 그것들을 사용하는 것에서 볼 수 있다. PC에서의 일반적인 프로그램에서는, 막대한 양의 문제들의 원인과 당신의 프로그램이 메모리 보호와 모든 것들에 충돌하는 원인이 된다.
우리가 비디오에 무언가 엉망으로 만들기 전에NES 내부에서 VBlank 주기라는 시간만큼 기다려야 한다. 이 주기는 다른 프레임을 위해 PPU를 갱신하거나 그림을 그릴 수 있게 해준다. 다 마쳤다면, 화면이 하드웨어에 의해 그려지기 시작하는 동안, 다음 프레임을 위한 로직으로 진행한다. VBlank의 종료와 시스템이 PPU 잠금을 풀고 그리기 시작하기 전에 매우 빠르게 PPU 설정을 해줘야 한다.
PPU는 자체 메모리가 있어서, 우선 두 개의 값인, 어디에 데이터가 있고, 그 데이터를 기록할 건지를 NES에 알려줘야 한다. 우리는 첫 번째 색상으로, 모든 부분의 배경색이 되는, 파란 색을 기록했다. 그리고 글자 색으로 흰색을 기록했다.
다음은, 내용을 아스키(ASCII) 문자열을 화면으로 출력하는데 도움을 주는 함수가 있다. 고맙게도, 기본 글꼴은 비디오 메모리에서 아스키로 정렬된다.
화면에 문자를 출력한 후에, 화면의 위치를 지정해 주면 우리가 기대했던 위치에 글자가 출력된다.
다 했기에, 다음 차례로 올 그림이 그려질 수 있게 이미지가 들어 올 것이다.(Since we are done, we then turn on the image so that it will be drawn in the coming picture.)
프로그램은 while loop까지만 수행하고 아무것도 안 했으므로, 프로그램은 무한히 반복되어 엉망이다.
Conclusion
NES 프로그래밍에 대해서 알아야 할 게 여전히 많기에, 매 연재마다 깊이있게 설명할 것이다. 평균적으로, 6502, NES 하드웨어 특징, 그리고 그밖의 다른 정보에 대해서 찾아보라. 또한, 좋아하는 NES 게임들에 초첨을 맞추고 게임에서 수행하는 것에 대해서 생각해 보라. 8x8 픽셀 타일들, 색상 사용, 다른 게임들의 동작 방식 들에 대해서 더 주의를 기울여라. 우리는 나중에 우리가 만든 홈브류를 많이 만들게 될 것이니, 지속적인 관심 바란다~
댓글 없음:
댓글 쓰기