본문 바로가기
프로그래밍/PSP

[펌]PSP 프로그래밍 103 - Hello World2

by 베리베리 2008. 7. 28.
1. main.c

전에 만든 Hello World 프로그램의 소스 코드를 보면 다음과 같다.

#include <pspkernel.h>
#include <pspdebug.h>

#define printf pspDebugScreenPrintf

/* Define the module info section */
PSP_MODULE_INFO("template", 0, 1, 1);

/* Define the main thread's attribute value (optional) */
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);

int main(int argc, char *argv[])
{
  pspDebugScreenInit();
  pspDebugScreenPrintf("Hello World\n");
  return 0;
}

PSP_MODULE_INFO 매크로는 프로그램의 이름과 속성, 그리고 버전 정보를 지정한다. 모든 PSP 프로그램에 꼭 들어가야 하는 부분이다. PSP_MODULE_INFO( name, attributes, major_version, minor_version )과 같이 값을 넣으면 된다. attributes는 아래와 같이 정의된 값을 사용하면 되는데, 대부분의 경우 USER 속성인 0을 사용하게 된다. 버전 정보는 취향껏 넣으면 된다. 위 예제의 경우 1.1을 넣은 경우이다.

enum PspModuleInfoAttr
{
  PSP_MODULE_USER = 0,
  PSP_MODULE_KERNEL = 0x1000,
};

다음 매크로들은 필요한 경우에만 사용한다. 프로그램의 여러가지 속성을 지정해 줄 수 있다. 인자로 넘겨줄 수 있는 값들은 pspthreadman.h를 참고하면 된다.

/* Define the main thread's initial priority. */
PSP_MAIN_THREAD_PRIORITY( priority )

/* Define the main thread's stack size (in KB). */
PSP_MAIN_THREAD_STACK_SIZE_KB( size_kb )

/* Define the main thread's attributes. */
PSP_MAIN_THREAD_ATTR( attr )
PSP_MAIN_THREAD_ATTRIBUTE
/* Define all main thread parameters. */
#define PSP_MAIN_THREAD_PARAMS( priority, size_kb, attribute )
/* If declared, the runtime code won't create a main thread for the program. */
#define PSP_NO_CREATE_MAIN_THREAD()
/* Declare the size of the heap (in KB) that the program wants to allocate from. */
#define PSP_HEAP_SIZE_KB( size_kb )
/* Declare the name of the main thread */
#define PSP_MAIN_THREAD_NAME( s )

그리고, main 함수 내에는 디버그용 화면을 초기화하고 Hello World를 화면에 출력하는 단순한 구성이다.


2. Makefile

빌드에 사용한 메이크 파일의 내용을 보면 다음과 같다.

TARGET = template
OBJS = main.o
INCDIR =
CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
LIBDIR =
LDFLAGS =
EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Template
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak

필요한 값들을 지정하고 PSPSDK의 lib 디렉토리에 있는 build.mak 파일을 이용해서 빌드를 수행하고 있다. 템플릿으로 활용하도록 하면 되므로 추후에도 바꿀 부분은 많지 않다.


3. XMB로 돌아가기

이전에 만든 Hello World는 HOME 키를 눌러서 XMB로 돌아가는 것 조차 할 수 없었기 때문에 콜드 파워 오프로 종료해야만 했다. HOME 키가 동작하게 하려면 다음 위치에 있는 샘플 코드를 살펴 보자.

C:\cygwin\usr\local\pspdev\psp\sdk\samples\debug\kprintf

위 디렉토리에도 역시 main.c와 Makefile이 들어 있다. main.c를 열어 보면 Hello World와 비슷하지만 다음과 같은 3개의 새로운 함수가 있다. 이 함수들을 카피해서 Hello World의 소스에 그대로 붙여넣자.

/* Exit callback */
int exit_callback(int arg1, int arg2, void *common)
{
  sceKernelExitGame();
  return 0;
}
/* Callback thread */
int CallbackThread(SceSize args, void *argp)
{
  int cbid;
  cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
  sceKernelRegisterExitCallback(cbid);
  sceKernelSleepThreadCB();
  return 0;
}
/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void)
{
  int thid = 0;
  thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, THREAD_ATTR_USER, 0);
  if(thid >= 0)
  {
       sceKernelStartThread(thid, 0, 0);
  }
  return thid;
}

SetupCallbacks 함수를 부르면 새로운 thread를 생성하는데, 이 thread는 종료 시의 콜백 함수를 등록하고 필요할 때까지 잠에 빠지게 된다. ExitCallback이 등록되면 HOME 키가 활성화되고 HOME 키를 누르고 게임을 종료한다고 선택하면 sceKernelExitGame 함수가 실행되며 XMB로 돌아가게 된다.

그리고, main 함수 내에서 SetupCallbacks 함수를 불러주도록 다음과 같이 main 함수에 코드를 추가한다. 마지막의 sceKernelSleepThread 함수는 thread를 재우게 하는 함수이다.

  SetupCallbacks();
  pspDebugScreenInit();
  pspDebugScreenPrintf( "Hello World\n" );
  sceKernelSleepThread();
  return 0;

다시 make kxploit 명령으로 빌드를 하고 만들어진 template 디렉토리와 template% 디렉토리를 PSP에 옮기고 실행을 한 후 HOME 키를 누르면 "Do you want to quit the game?" 화면이 나오고 Yes를 선택하면 프로그램이 종료되고 XMB로 돌아가게 된다.


4. Corrupted Data 없애기

추가로 Corrupted Data가 나오지 않게 하는 방법 중 하나를 사용해 보자. template 디렉토리와 template% 디렉토리를 각각 다음과 같이 이름을 변경한다.

template -> __SCE__template
template% -> %__SCE__template

실행을 하기 위해 XMB의 게임, 메모리 스틱으로 들어가면 Corrupted Data가 없고 Template 아이콘 하나만 있을 것이다. 물론 실행에도 문제가 없다.


이제 좀 프로그램다운 프로그램을 만들게 되었다, 축!

출처 : http://www.onlinegamer.co.kr/ 지금은 사라져서;; 공개해두 괜찮을지;;;

댓글