2007년 12월 15일 토요일

Visual Basic에서 TaskBar 사이즈 얻어오기

Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Public Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
End Type

    Dim hTaskbar As Long
    Dim rTaskbar As RECT
    Dim sClass As String
    sClass = "Shell_TrayWnd"
    hTaskbar = FindWindow(sClass, "")
    GetWindowRect hTaskbar, rTaskbar

API Guide

이 글을 보는 모든 프로그래머에게 엄청나게 유용한 프로그램을 소개한다.

바로 API-Guide..
물론 아는 사람들도 많겠지만, 프로그래머를 바보로 만드는 유명한 프로그램이라 소개한다.

비주얼베이식 프로그래머들의 고질적인 단점이 뭘까...
바로.. Win32 API 가 뭔지도 모른다는거다. 비베의 한계를 뛰어넘기 위해서는
Win32 API를 써야 함에도 불구하고 많은 후잡 프로그래머들은 비베의 한계를 느끼고
프로그래밍을 접거나, MFC 쪽으로 넘어가고 만다.

이 글을 쓰고 있는 나도 고등학생때까지 비베에서 API라는 걸 쓰는 건 알고 있었지만
어떻게 써야 하는지 전혀 몰랐다.

자.. 여기 그런 프로그래머들을 위한 프로그램을 소개한다.
API Guide 는 약 1000개정도의 비주얼 베이식에서 사용할 수 있는 API를 간편하게 정리해놓은
프로그램이다. 물론 덤으로 그에 따른 예제까지 실어주고 있다.

너무 좋아하지는 마라..

이런 프로그램.. 예를 들어 VA(Visual Assistance)와 같이 프로그래머의 손을 더 쉽게 해주는 프로그램을 많이 쓰면 어느 순간에 그런것들이 없으면 프로그래밍이 불가능한 바보가 될지도 모르니깐... 정말 모를때만 쓰고 왠만하면 MSDN을 참고하는 습관을 들이자.

MSDN에는 API가 C 문법 위주로 나와 있는데 데이터 형만 잘 이해하고 있다면
Visual Basic에서도 얼마든지 사용 가능하다.

이상!

2007년 12월 14일 금요일

Linux Tomcat 설치

다음은 생전 처음으로 리눅스에 톰캣을 설치한 내용을 적은 메모이다.



톰캣 다운로드

다운로드 URL : http://tomcat.apache.org/

위의 URL에서 톰캣을 다운받는다.

이 문서에서는 apache-tomcat-5.5.17.tar.gz 를 다운받았다.



톰캣 설치

다운 받은 apache-tomcat-5.5.17.tar.gz를 /usr/local/src 로 옮겼다.

#tar xvfz apache-tomcat-5.5.17.tar.gz [enter]

/usr/local/src/apache-tomcat-5.5.17 디렉토리가 생기고 그 안에 톰캣이 깔린다.

이 디렉토리를 /usr/local 로 옮겼다.

#mv apache-tomcat-5.5.17 /usr/local [enter]



톰캣 실행

# cd /usr/local/apache-tomcat-5.5.17/bin [enter]
# ./startup.sh [enter]



톰캣 실행 확인

브라우저에서 http://192.168.0.2:8080 를 넣어 고양이가 나오는지 확인




톰캣 관리화면 활성화 시키기

다음 파일을 편집한다.
# vi /usr/local/apache-tomcat-5.5.17/tomcat-users.xml [enter]

다음 내용을 추가시킨다.
<role rolename="manager"/>
<user username="admin" password="admin" roles="manager"/>

톰캣을 다시 재실행한다.

#/usr/local/apache-tomcat-5.5.17/bin/shutdown.sh [enter]
#/usr/local/apache-tomcat-5.5.17/bin/startup.sh [enter]


톰캣 관리화면을 열어본다.

브라우저에서 http://192.168.0.2:8080/manager/html
ID : admin
Password : admin



톰캣 클래스패스 설정하기

#vi /etc/profile [enter]

다음 내용을 넣는다.(주로 가장 마지막에...)
CATALINA_HOME="/usr/local/apache-tomcat-5.5.17"
export CATALINA_HOME
CLASSPATH=".:$CATALINA_HOME/lib/servlet.jar"
export CLASSPATH


* 위에서 CLASSPATH의 경우는 이미 CLASSPATH가 정해져 있다면
  처음에 $CLASSPATH를 넣어주거나
  기존의 CLASSPATH 정의부분의 뒤쪽에 이어서 입력해 준다.

저장하고 나온 후
#source /etc/profile [enter]


---- 참고 ----
http://cafe.naver.com/bestreal.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=221

2007년 12월 12일 수요일

Fedora 4 YUM 설정

출처 : http://iparid.egloos.com/1709753

yum.repo.d 설정 (FC4)
/etc/yum.conf 설정은 레뎃9 시절 등등 예전 자료가 많았지만, FC3부터 /etc/yum.repos.d/* 여섯개의 파일로 분산되면서 새로운 설정 방법을 설명한 곳을 한참 뒤져보았다. 인터넷에서는 한 군데 FC3 기준으로 설명해 놓았다. 요걸 보고 조금 고쳐서 FC4에 맞게 설정하는 법, 또 원리 등등을 조금 적어 보겠다.

원래 들어있는 파일은 6개다.

fedora.repo
fedora-devel.repo
fedora-extras-devel.repo
fedora-extras.repo
fedora-updates.repo
fedora-updates-testing.repo

여기에서 인스톨에 fedora.repo, 업데이트에 fedora-updates.repo를 쓴다. 일단 요것만 고쳐보자.

<원본 fedora.repo>
name=Fedora Core $releasever - $basearch - Base한글
#baseurl=http://download.fedora.redhat.com/pub/fedora/linux/core/$releasever/$basearch/os/
mirrorlist=http://fedora.redhat.com/download/mirrors/fedora-core-$releasever
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora


baseurl에 주석 처리가 되어있으니 결국 mirrorlist 행이 관건인 셈이다. $releasever는 자기 페도라 버전에 따라 현재까지 1~5로 나타난다. 그럼 주소에 나와 있는 fedora-core-4 파일을 열어보자.

http://download.fedoraproject.org/pub/fedora/linux/core/4/$ARCH/os/
http://mirror.linux.duke.edu/pub/fedora/linux/core/4/$ARCH/os/
http://fedora.mirrors.tds.net/pub/fedora-core/4/$ARCH/os/
...
...


가능한 미러가 66개 나와있다. 그런데 제일 느린 서버가 1순위이므로 접속은 되지만 느려터져 답답하다. 따라서 커스텀 미러 리스트 파일을 작성하자. Updates가 들어있는 디렉토리 주소가 조금 다르다. 한국 서버가 가장 빠르기는 하지만 이 포스트를 작성하는 시점에서 404 에러를 토했기 때문에 속도는 조금 떨어져도(200-500kB/s 정도) 믿음직스러운 kernel.org를 1순위로 잡았다.

<custom-BASE>
http://mirrors.kernel.org/fedora/core/4/$ARCH/os
ftp://ftp.kreonet.re.kr/pub/Linux/fedora/core/4/$ARCH/os
ftp://mirror.hostway.co.kr/pub/fedora/4/$ARCH/os
ftp://ftp.kaist.ac.kr/pub/fedora/linux/core/4/$ARCH/os


<custom-UPDATES>
http://mirrors.kernel.org/fedora/core/updates/4/$ARCH
ftp://ftp.kreonet.re.kr/pub/Linux/fedora/core/updates/4/$ARCH
ftp://mirror.hostway.co.kr/pub/fedora/updates/4/$ARCH
ftp://ftp.kaist.ac.kr/pub/fedora/linux/core/updates/4/$ARCH


그럼 fedora.repo, fedora-updates.repo 기존의 mirrorlist를 주석처리하고, 새로운 주소로 설정하자.
gpgcheck도 꺼놓으면 성가시지 않다.

<고친 fedora.repo>
mirrorlist=file:///etc/yum.repos.d/custom-base
gpgcheck=0


<고친 fedora-updates.repo>
mirrorlist=file:///etc/yum.repos.d/custom-updates


다시 실행할 서비스 없이 다음에 yum 실행할 때 바로 적용된다.

2007년 12월 11일 화요일

Tomcat in Fedora4

설치순서
1. apache(httpd-2.0.54, source)
2. apache-tomcat-connector(jakarta-tomcat-connectors-1.2.14.1-src, source)
3. tomcat(jakarta-tomcat-4.1.31, binary)
4. setting


1-1) ./configure --prefix=/usr/local/apache2 --enable-mods-shared=most --enable-modules=so --with-mpm=worker
1-2) make
1-3) make install
1-4) echo "/usr/local/apache2/lib" >> /etc/ld.so.conf
     echo "/usr/local/apache2/modules" >> /etc/ld.so.conf
     ldconfig
============================================================================================================


2-1) ./buildconf.sh
2-2) ./configure --with-apxs=/usr/local/apache2/bin/apxs
2-3) make
2-4) make install
2-5) /usr/local/apache2/conf/httpd.conf 파일수정
     모듈추가라인 가장 아래 다음과 같이 추가
     LoadModule jk_module modules/mod_jk.so
============================================================================================================


3-1) /usr/local/tomcat 에 설치
3-2) /usr/local/tomcat/conf/server.xml 파일수정
     서비스 컨텍스트 추가
     <Host name="xxx.xxx.co.kr">
         <Context path="" docBase="/home/xxx/public_html"
                  reloadable="true"/>
         <Alias>xxx.xxx.co.kr</Alias>
      </Host>
============================================================================================================


4-1) /usr/local/tomcat/conf/auto/mod_jk.conf 파일수정(없으면 생성)
다음과 같이 생성
<IfModule !mod_jk.c>
  LoadModule jk_module libexec/mod_jk.so
</IfModule>
JkWorkersFile "/usr/local/tomcat/conf/jk/workers.properties"
JkLogFile "/usr/local/tomcat/logs/mod_jk.log"
JkLogLevel emerg
<VirtualHost localhost>
    ServerName localhost
    JkMount /tomcat_admin ajp13
    JkMount /tomcat_admin/* ajp13
    JkMount /webdav ajp13
    JkMount /webdav/* ajp13
    JkMount /examples ajp13
    JkMount /examples/* ajp13
    JkMount /tomcat-docs ajp13
    JkMount /tomcat-docs/* ajp13
    JkMount /manager ajp13
    JkMount /manager/* ajp13
</VirtualHost>

4-2) /usr/local/tomcat/conf/jk/workers.properties 파일수정(없으면 생성)
다음과 같이 생성
# Start setup file
#
workers.tomcat_home=/usr/local/tomcat
workers.java_home=/usr/local/java
ps=/
worker.list=ajp12, ajp13
# Definition for Ajp13 worker
#
worker.ajp13.port=8009
worker.ajp13.host=localhost
worker.ajp13.type=ajp13
#
# End setup file


4-3) /usr/local/tomcat/conf/web.xml 파일수정
<web-app> tag 내에 추가

   <filter>
    <filter-name>Set Character Encoding</filter-name>
    <filter-class>filters.SetCharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>EUC_KR</param-value>
    </init-param>
  </filter>
  <filter-mapping>
      <filter-name>Set Character Encoding</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

4-4) 한글변환 문자 셋 / 디렉토리에 압축 풀기 (tar -zxvf classes.tgz -C /)

4-5) /usr/local/apache2/conf/httpd.conf 파일수정
다음과 같이 추가
JkWorkersFile /usr/local/tomcat/conf/jk/workers.properties
Include /usr/local/tomcat/conf/auto/mod_jk.conf
JkLogFile /usr/local/tomcat/logs/mod_jk.log
JkLogLevel emerg

4-6) /usr/local/apache2/conf/httpd.conf 파일수정
버츄얼 호스팅 설정
#NameVirtualHost *:80   (주석제거)

다음과 같이 추가
<VirtualHost *:80>
    ServerAdmin root@xxx.xxx.co.kr
    DocumentRoot /home/xxx/public_html
    ServerName xxx.xxx.co.kr
    JkMount  /*.jsp ajp13
    JkMount  /servlet/* ajp13
</VirtualHost>

4-7) /etc/profile(환경변수 수정)
export LC_ALL=ko_KR.eucKR
export LANG=ko_KR.eucKR
JAVA_HOME=/usr/local/java
CATALINA_HOME=/usr/local/tomcat
PATH=$PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
export JAVA_HOME CATALINA_HOME
export set CLASSPATH=.:$CLASSPATH=/usr/local/java/lib/tools.jar:.:/usr/local/java/lib/dt.jar:/home/xxx/public_html/WEB-INF/lib/jCharts-0.7.0.jar:/home/xxx/public_html/WEB-INF/lib/Acme.jar:.:
export set CLASSPATH=.:$CLASSPATH=$CLASSPATH:/home/xxx/public_html/WEB-INF/lib/mysql-connector-java-3.1.7-bin.jar:/home/xxx/public_html/WEB-INF/lib/jxl.jar:/home/xxx/public_html/WEB-INF/lib/activation.jar:/home/xxx/public_html/WEB-INF/lib/mail.jar:/usr/local/java/lib/jfreechart-0.9.16.jar:.:
export set CLASSPATH=.:$CLASSPATH=$CLASSPATH:/home/xxx/public_html/WEB-INF/classes:.:
export set CLASSPATH=.:$CLASSPATH=$CLASSPATH:/home/hurec/public_html/WEB-INF/classes:.:
export set CLASSPATH=.:$CLASSPATH=$CLASSPATH:/usr/local/tomcat/common/lib/servlet.jar:.:

아파치와 톰캣 연동(펌)

mod_jk를 사용해서 아파치 2 와 톰캣 5.5를 연동하기

1: 아파치 2를 설치한다.

httpd-2.0.55의 소스를 받아 설치한다.
./configure --enable-so --enable-mods-shared=most --prefix=/usr/local/apache2.
make
make install

2: 자바(JDK 1.5이상)를 설치한다.

/usr/local/java 등의 위치에 설치하고, /etc/profile 제일 아랫줄에
export JAVA_HOME=/usr/java/jdk1.5.0_05
라고 추가하고,
source /etc/profile 명령을 실행해서 변경을 적용시킨다.


3: 톰캣 5.5 설치

apache-tomcat-5.5.12.tar.gz 를 다운받아 /usr/local 에 놓고 root 권한으로 아래와 같이 실행한다.

cd /usr/local
tar xvfz apache-tomcat-5.5.12
ln -s /usr/local/apache-tomcat-5.5.12 /usr/local/tomcat
groupadd tomcat
useradd tomcat -g tomcat -d /usr/local/tomcat tomcat
chown -R tomcat.tomcat /usr/local/apache-tomcat-5.5.12 /usr/local/tomcat

/etc/profile에 아래의 내용을 추가하고 적용한다.

export PATH=$PATH:/usr/local/bin:/usr/local/tomcat/bin
export JAVA_HOME=/usr/java/jdk1.5.0_05
export CATALINA_HOME=/usr/local/tomcat

위의 내용을 추가했으면,

source /usr/profile을 실행


톰캣 서버 실행 테스트

톰캣 디렉토리의 bin디렉토리가 PATH에 포함된 것을 확인하고,
startup.sh
을 실행하면 톰캣이 실행된다.

ps -def | grep tomcat
이라고 실행할 때
tomcat 18591 1 88 06:40 pts/0
와 비슷한 내용이 보이면 톰캣 서버가 실행된 것이다.
 
shutdown.sh
을 실행하여 톰캣 서버를 멈추고서, 다시
ps -def | grep tomcat

을 실행하면 위의 내용이 보이지 않게 된다.


4: mod_jk 설치하기
 jakarta-tomcat-connectors-1.2.14.1-src.tar.gz 를 다운받고 아래처럼 실행한다.

cd jakarta-tomcat-connectors-1.2.14.1-src/jk/native
./buildconf.sh
./configure --with-apxs=/usr/local/apache2/bin/apxs
make

make install

mod_jk.so 가 /usr/local/apache2/modules 디렉토리 안에 있고, 권한은 755로 설정되어있는지 확인한다..

5: 아파치를 톰캣에 연결하기

/usr/local/apache2/conf 디렉토리에 workers.properties 라는 이름의 파일을 만들고 아래의 내용을 입력한 후 저장한다.

workers.tomcat_home=/usr/local/tomcat
workers.java_home=/usr/java/jdk1.5.0_05
ps=/
worker.list=default

worker.default.port=8009
worker.default.host=localhost
worker.default.type=ajp13
worker.default.lbfactor=1

httpd.conf 에 아래의 내용을 추가한다.
#
# Mod_jk settings
#
# Load mod_jk module
LoadModule jk_module modules/mod_jk.so
# Where to find workers.properties
JkWorkersFile conf/workers.properties
# Where to put jk logs
JkLogFile logs/mod_jk.log
# Set the jk log level [debug/error/info]
JkLogLevel debug
# Select the log format
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
# JkOptions indicate to send SSL KEY SIZE,
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
# JkRequestLogFormat set the request format
JkRequestLogFormat "%w %V %T"
# Send JSPs for context /jsp-examples to worker named default
JkMount /jsp-examples/*.jsp default
# Send servlets-examples to worker named default
JkMount /servlets-examples/* default

Keep editing httpd.conf and add following Alias directives (for example under the entry for the icon Alias). These directives tell Apache to map /jsp-examples and servlets-examples to the sample directories that ship with Tomcat.

# Static files in the jsp-examples webapp are served by apache
Alias /jsp-examples "/usr/local/tomcat/webapps/jsp-examples/"

Options FollowSymLinks
AllowOverride None
Allow from all


# The following line prohibits users from directly access WEB-INF

AllowOverride None
deny from all


# Static files in the servlets-examples webapp are served by apache
Alias /servlets-examples "/usr/local/tomcat/webapps/servlets-examples/"

Options FollowSymLinks
AllowOverride None
Allow from all


# The following line prohibits users from directly access WEB-INF

AllowOverride None
deny from all


아파치를 재구동한다.

http://Web_server_name_or_IP:8080에 접속해 본다.

http://Web_server_name_or_IP/jsp-examples

http://Web_server_name_or_IP/servlets-examples 에 접속하여 연동을 확인한다

2007년 11월 14일 수요일

What's the smallest Windows CE 5.0 configuration that you can target from Visual Studio 2005?

What's the smallest Windows CE 5.0 configuration that you can target from Visual Studio 2005?

Very small!  The DeviceEmulator nk.bin can be as small as 1.3mb!  With that 1.3mb OS image, you can deploy and debug native applications using Visual Studio for Devices.  Here's how...

In Platform Builder

Install the Device Emulator BSP from http://www.microsoft.com/downloads/details.aspx?FamilyID=474b03a6-e87d-455d-bc16-b8cf18ef39b4&displaylang=en.  Pay special attention to the non-skin configuration options in the SDK XML file.

Create a new platform using the wizard...

  • Step 4 - choose custom device
  • Step 5 (Applications and Services Development) - check "C Libraries and Runtimes" (which checks everything underneath it)
  • Step 6 (Applications - End User) - leave everything unchecked
  • Step 7 (Core OS) - check "Power Management (Minimal)", "Device Manager", and "Debugging Tools \ Toolhelp API"
  • Step 8 (Networking Features) - check "Networking Features \ Winsock Support"
  • Step 9 (Device Management) - leave everything unchecked
  • Step 10 (File Systems and Data Store) - check "File System - Internal (Choose 1) \ RAM and ROM File System" and "Registry Storage (Choose 1) \ Hive-based Registry"
  • Step 11 (Fonts) - leave everything unchecked
  • Step 12 (International) - check "Locale Services (Choose 1) \ National Language Support (NLS)"
  • Step 13 (Internet Client Services) - leave everything unchecked
  • Step 14 (Grahics and Multimedia Technologies) - leave everything unchecked
  • Step 15 (Security) - leave everything unchecked
  • Step 16 (Shell and User Interface) - check "Graphics, Windowing and Events \ Minimal Input Configuration"
  • Step 17 (Windows CE Error Reporting) - leave everything unchecked
  • Step 18 (Voice over IP Phone Services) - leave everything unchecked
  • Finish!

Now, go to the Platform\Settings menu, and for the release configuration, switch to the Build Options tab and uncheck "Enable CE Target Control Support (SYSGEN_SHELL=1)" and "Enable KITL (no IMGKITL=1)".

Then switch to the Environment tab and add "BSP_NOTOUCH" with value "1"

Now build it using the Platform Builder "Build OS \ Sysgen" menu.  The retail nk.bin image will be about 1.3mb in size.

Next, create an SDK for it.  Go to Platform Builder's "Platform \ SDK \ New SDK..." menu, fill in the details on the first page, then leave the defaults for the rest.

Finally, build the SDK using the Platform Builder "Platform \ SDK \ Build SDK" menu.


Install the SDK

Install the new SDK on your Visual Studio 2005 machine.

Now comes the hacky part of the process you need to hack your datastore a little.

  • Navigate to C:\Documents and Settings\All Users\Application Data\Microsoft\corecon\1.0\addons and look for the newest .xsl file whose name is a GUID.  Open that file in notepad or your favorite XML editor
  • Edit the RemoteCcClientFile, RemoteCcShutdownFile, RemoteCcTransportLoaderFile and RemoteCcCMAcceptFile properties, removing the "%CSIDL_WINDOWS%" text and just deploying to the root directory.  There are two instances of each property, one for emulator targets and one for hardware device targets.  Edit both instances of each property.
  • Edit the RemoteTransportFile property, again, removing the %CSIDL_% constant, so that the dmatrans.dll deploys to the root directory.
     

 ie.

<PROPERTY ID="RemoteCcCMAcceptFile" Protected="true">%CSIDL_WINDOWS%\CoreCon%CcVersion%\CMAccept.exe</PROPERTY>

becomes
<PROPERTY ID="RemoteCcCMAcceptFile" Protected="true">\CoreCon%CcVersion%\CMAccept.exe</PROPERTY>

If something goes wrong, delete the XML file, uninstall and reinstall your SDK, and it will be recreated.

Use the SDK from Visual Studio 2005

Launch Visual Studio, and do a File/New Project, to create a new C++ SmartDevice project.  Pick your SDK from the list of targets, and select "Console" as the application type, with no ATL or MFC support.

Once the wizard has finished, there are a few work items left:

  • Remove the #include of commdlg.h from the top of the wizard-generated .cpp file
  • Remove the #include of atlcecrt.h from the bottom of stdafx.h
  • In the project properties, make the following edits in the "All Configurations" configuration:
    • Under Configuration Properties \ Linker, click on Additional Dependencies then type in this text:  coredll.lib corelibc.lib $(NOINHERIT)
    • Under Configuration Properties \ Deployment, edit the "Remote Directory" entry, removing the "%CSIDL_PROGRAM_FILES%" text.  Deploy your app into a subdirectory under the root directory.
  • Make the following edit to your project properties under both the Debug and Retail configurations:
    • Under Configuration Properties \ Debugging, remove the "%CSIDL_PRGORAM_FILES%" text.  The remote executable is in a subdirectory under the root directory.

Now, F5 should build your app, launch the emulator, deploy and debug.


Diagnosing Problems

  • If the emulator launches but deployment isn't happening, you might have left a %CSIDL_*% constant in a path somewhere. 
  • Go to VS's Tools/Options dialog and navigate to "Device Tools \ Devices", click on your emulator entry and click Properties.  In the emulator properties dialog, click "Emulator Options" then on the Peripherals tab, check the "Create text console for serial port 1" checkbox.  This will cause the emulator to open a console window as it launches, that will show you diagnostics output from the Windows CE kernel.

What's with the CSIDLs? 

Visual Studio for Devices must resolve %CSIDL_% symbols in pathnames by executing code on the device/emulator, that calls SHGetSpecialFolderPath().  The OS image size grows substantially if we pull that API in, as it only comes in as part of the GUI shell.

We must painstaking remove all %CSIDL_% symbols from the datastore and project properties.  Otherwise, VSD's device-side code will go into a long polling loop waiting for the shell APIs to come online, and when the timeout eventually expires, the VSD operation will fail.


2007년 10월 22일 월요일

광산김씨

신라 신무왕의 셋째아들 흥광()을 시조로 하는 광산김씨()는 한국의 대표적인 가문의 하나로서 '광김'으로 일컫는다. 이 가문은 조선시대에 총 265명의 문과 급제자를 배출하여, 본관별 서열로 제5위가 되었다. 여기에서 정승이 5명, 대제학이 7명, 청백리가 4명, 왕비가 1명이 나왔는데, 특히 대제학 7명은 ‘광김’을 더욱 빛나게 한 사계() 장생()의 자손이다.

광산김씨는 고려 초기 삼중대광()에 오른 3세손 길()로부터 8대에 걸쳐 평장사()를 배출하여 명문 가문의 기반을 이루었으며, 15세손으로 역시 삼중대광에 오른 정()의 아들인 약채()·약항()·약시() 3형제대에서 더욱 번창하기 시작하였다. '광김'의 첫 정승(좌의정)을 지낸 국광()과 영의정을 지낸 극성()은 이들의 후손이며, 장생은 국광의 5대손이다. 그는 예학()의 태두로서 그의 학문은 이조판서를 지낸 아들 집()에게 계승되어 부자가 문묘()에 배향()되는 전무후무한 영광을 누리기도 하였다. 집의 아우 반()의 여섯 아들은 모두 출중하고, 후손이 크게 번창하여 ‘광김’의 전성기를 이루었다.

청구영언》을 낸 가인() 천택(), 영의정 상복(), 우의정 희(), 이조판서 상휴()·기만()·기은(), 대제학 만기()·만중() 형제 등이 모두 이들의 후손이다. 이 가운데 총융사(使)를 지낸 만기와 《구운몽》 《사씨남정기》의 작가로 유명한 만중의 후손 중에서 많은 인물이 나와 ‘사계 자손’의 주축을 이루었다.

예조판서·대제학을 지낸 진규()는 만기의 아들이며, 대제학·영의정을 지낸 양택()은 진규의 아들로서 3대 대제학, 형제 대제학의 진귀한 기록을 남기기도 하였다. 시문집 10권을 남긴 문인 춘택(), 고종 때 이조판서·대제학을 지낸 영수()는 진규의 형이며, 판서·참찬을 지낸 진구()의 후손이다. 2000년 인구조사에서 25만 8936가구에 83만 7008명이 살고 있는 것으로 나타났다.

2007년 9월 12일 수요일

제로보드 XE

지금의 인터넷은 바야흐로 블로그의 천국이다.
대부분의 포탈사이트에서는 블로그 서비스를 기본적으로 지원하고 있고...
사용자들도 많이는 쓰지 않지만 옛날 이메일 주소 하나쯤은 가지고 있듯이 블로그도 하나쯤은 가지고 있다.

나 역시 다음, 네이버, 티스토리 등등 여러 사이트에 블로그를 가지고 있다.
하지만 내생각에 자기만의 주소를 가질수 있는 설치형 블로그가 주도권을 잡지 않을까 한다.

많은 프로그래머들 아니면 컴퓨터 산업에 종사하는 사람들은 블로그가 나오기 전에 wiki 를 이용하여 자기가 하는 일이나 생각을 표현하고 했었다. 하지만 설치형 블로그가 많이 생겨나자 요즘 wiki 는 거의 볼수가 없다...

나는 예전에 Zog 라고 해서 제로보드에 약간의 변형을 가져온 설치형 블로그를 사용했다. 그 당시에는 획기적인 것이라고 많이 생각했고 많은 자료를 날려먹기 전에는 Zog 빠돌이였다.
하지만, 제로보드에서 파생된것이기 때문에 어딘가 많이 부족한 점이 있었다.. 관리도구를 보면 제로보드의 것을 그대로 사용한 점도 있었고 제로보드에서 보안 패치를 하게되면 것잡을수 없이 꼬이던것이 생각난다.

제로보드는 아마도 우리나라에 가장 많이 사용된 BBS 솔루션일거다. 논외거리이지만 제로보드의 문제점을 짚어보자면, 너무 덩치가 큰 라이브러리 또는 스킨기능을 쉽게 소스코드를 줄이기 위해 빈번히 사용되는 include 등이 사용하는 사람이나 약간의 수정을 하는 사람을 너무 골치 아프게 했고 스킨에 약간 오류가 있을경우 제로보드에 불신까지 느껴지는 단점이 존재하고 있었다.

Zog 역시 제로보드 기반이라 그런 고질적인 문제는 해결되지 못하였고, Zog 를 쓰던 많은 사람들이 다른 설치형 블로그로 옮겨갔다. 나 역시 지금은 TatterTools 를 쓰고 있다.

그런 제로보드가 새로운 변화를 시도하고 있다. 이름하여 제로보드 XE 잠시 zero 님의 블로그를 가서 이블로그가 뭐인가... 찾아봤는데.. 제로보드XE 였다. 이런생각을 하면 안되지만 잠시 동안 "피식" 이라는 쓴 웃음은 감출수가 없었다.

제로보드 나름대로 블로그가 만연하는 이 인터넷 세상에서 살아남고자 하는 발버둥이겠지만... 오픈베타에서도 "그냥 자기 홈페이지에 제로보드 붙이던 사용자"들에게 태클을 걸리고, 체계적이지 못한 개선점 및 버그 리포팅 때문에 개발자가 고생을 한다고 한다...

나의 개인적인 입장에서는 너무 늦은 변화시도가 아닌가 싶다. 이미 설치형 블로그는 Tattertools 가 판도를 장악하고 있고, 그 동안 몇명 사람들에게 외면이나 실소를 짓게 한 제로보드가 블로그 솔루션을 만든다고 해서 써볼사람이 몇명이나 될까 하는 의구심이 든다.

물론 누구나 한번쯤은 어떤것인가 생각하고 써볼수는 있겠지...

새로운 진화를 시도하는 제로보드XE 예전 BBS 세계에서 제왕의 자리에 앉았던것처럼 블로그도 성공할려면 예전에 많은 개발자나 사용자들에게 지적되었던 고질적인 문제점 그리고 지금 많은 설치형 블로그와 차별화 되는 많은 기능을 제공해야 그나마 시선이라도 받을수 있을거라고 생각한다.

사실 난 부정적으로 생각하고 있지만... 새로운 진화 시도... 해볼만하다.

2007년 9월 3일 월요일

iPAQ HX4700 에 리눅스 설치하기 #4

시리얼 싱크 케이블 만들기

모두 실험을 한번씩 해보았는가?
이번고에서는 IPAQ 을 텍스트 환경에서 제어하기 위한 싱크케이블을 만들어보도록 하겠다.
정확하게 얘기하자면 커널이 올라가기전... 음.. 화면이 뜨기전 제어할 수 있는 환경...
부트로더에 접근할 수 있는 환경이 되겠다.

http://opdenacker.org/pda/ipaq/connector/ipaq_connector.png

원본 그림이고, 친절하게 본고에도 첨부한다.

사용자 삽입 이미지

잘 안보이시는 분은 확대해서 보길 바란다.

만드는 방법이야 인터넷을 뒤지면 다 나오겠지만 부품을 어떻게 구하는지도 중요하다.
시리얼 부분은 컴퓨터 가게 가면 파는 시리얼 케이블 하나 작살내면 되는거고,

문제는 IPAQ 커넥터 부분인 상당히 구하기가 까다롭다.

구하는 방법 1번... 옥션에서 IPAQ_USB 싱크케이블을 구해서 하드코어적인 방법으로
개조한다. 왜 하드코어라고 부르냐면 그런 싱크케이블은 핀이 USB 전송에 필요한 핀밖에
없다. 그런걸 사게 되면 커넥터에 있는 핀을 모조리 빼서 시리얼용으로 새로 박는 수 밖에
없다. 필자는 그렇게 했다. 참고로 싱크 케이블을 3천원 정도면 구할 수 있다.
실패할걸 고려해서 한 3개정도 구입하자.

구하는 방법 2번 HP 홈페이지에서 다음 그림과 같은 커넥터를 산다.
사용자 삽입 이미지

분해해보면 알겠지만 핀이 전부다 구비되어 있고 납땜하기도 쉽게 잘 되어 있다.
하지만 생긴것 자체가 위험한 실험을 하기엔 럭셔리 하고 가격도 비싸다 약 9000원...
손재주가 부족하거나 땜질에 자신없는 분들은 이런 커넥터를 구입해서 하기 바란다.

구하는 방법 3  그런 커넥터를 전문적으로 만들어서 파는 사람들이 있다. 위에 실린 그림에도
약 26달러에 구입할 수 있다고 적어놨는데 국내에도 있다. 우리나라돈으로 하면 약 2만 7,8 천원 될거 같은데... 어떤 쇼핑몰에서 보긴 봤는데 4만 5천원 하더라.... 도둑놈들...

뭐 이랬거나 저랬거나 케이블을 만들어본다. 다음그림은 필자가 만든 케이블의 모습이다.
사용자 삽입 이미지

3000원 짜리 싱크케이블을 사서 하드코어로 만들었다. 두개 만들었는데 하나는 어디간지 모르겠고... 만드는데 1시간정도 걸린것 같다. 소요비용 약 5000원...

자 그리고 만들땐 필요없는 USB 부분은 과감히 빼버리도록 하자 어짜피 싱크는 시리얼로 이루어지기 때문에 USB 부분은 필요가 없다. 선 가르는것도 귀찮고 나노테크 레벨의 땜질이 필요하기 때문에 시리얼만 연결하도록 한다.

케이블을 다 만들었으면 테스트 해야 하는데 테스트 하는 방법은 Active Sync 에서 싱크방법을 시리얼 방식으로 해서 싱크 해보면 된다. 싱크가 잘되면 케이블을 잘 만들어진것이다.

아 한가지 더.. 이런 시리얼 통신을 해본 사람이면 대충 예상하고 있겠지만...
TXD, RXD, GND 만 연결하면 된다!!! 쓸데 없는 핀은 과감히 제거해서 땜질 과정을 간단하게
소화시켜야 된다.
우리가 케이블 만들려고 이글을 보고 있지는 않은 거니깐...

2007년 7월 22일 일요일

아프가니스탄 납치사건

한국인 기독교인 23명이 탈레반에 납치되었단다.
사상 최다 인원이 납치된거라던데...

그 사람들의 잘못을 말하자면 수없이 많겠지만 몇가지 짚어보자

1. 위험한 아프가니스탄에는 왜 갔나?
    봉사활동을 하러 갔대나... 문제는 왜 봉사활동을 하러 아프가니스탄에 갔을까?
    아프가니스탄은 이슬람이다. 이슬람은 우상 숭배나 타 종교에 대한 적대성이 강한 종교
    이다. 그런 종교가 국교인 나라에서 기독교인들이 뭐할려고 했을까?
    그리고, 한국에는 봉사활동 할만한 곳이 없나? 외국에 나가서 봉사활동 하면 주님의 은혜
    를 더 받을 거라는 착각을 한거냐?
    내 생각으로는 해외여행겸 봉사활동겸 나간것 같은데, 만약 이렇다면 비난받아 마땅하고
    샘물교회 사람들은 더 이상 해외 봉사활동 같은걸 하면 안된다.
    내 생각에 반박을 하고 싶다면 왜 해외로 나가서 봉사활동을 한건지 명확하고 논리적으로
    설명해주길 바란다.

2. 왜 위험을 감수하면서 육로로 이동했나?
    위험한 아프가니스탄, 몸사려도 시원찮을텐데 왜 위험을 무릎쓰고 육로로 이동을 했을까
    봉사활동 끝나가는 마당이라 긴장이 풀렸나? 아니면 해외에 나갔다고 가족들 선물사고
    그런다고 육로 이동할 경비밖에 남지 않았나? 궁금하다.

3. 위험한 육로 이동하면서 호위를 받지 않았나?
    일반적으로 위험한 이동을 할때면 경찰이나 경호업체에 호위를 받는다고 하던데, 뉴스에
    는 이런저런 복잡한 절차 때문에 그런걸 신청하지 않았다고 한다. 복잡한 절차라 복잡해
    봤자 지금보다 복잡하겠나? 아니면 복잡한 절차를 피해야할 구린 뒷구석이 있는지도 모를
    일이고... 복잡한 절차를 거칠바엔 목숨걸고 이동해보자 라는게 당시 사람들의 생각이었
    다면, 지금 예상대로네...

가족들 입장... 왜 가지말란곳 가서 위험해 지니깐 정부한테 책임지라고 하는건지? 정부가
나서서 돈으로 그사람들 풀어주면... 그거 누구 돈인가? 국민 혈세 아닌가? 너무 이기적이다.
유서까지 쓰고 갔다는 소문이 있던데 사실인지 거짓인지 모르지만 만약 그렇다면 죽을것을
알고서도 갔다는 얘기가 되는데... 순교 할 수 있는 절호의 기회라고 생각하는건 나뿐인가?

샘물교회 목사님들은 참 잘하고 계십니다. 순교하실려고 젊은 교인들까지 다 끌고 가시는
군요.

일단 사람이 죽고 사는 문제이기 때문에, 일단 살리고 봐야겠지... 그래 살아돌아와야지...
그럼 나는 정부에게 한가지 바라는게 있다. 나랏돈으로 그사람들 살려주고, 그사람들 살아
돌아오면 평생 그돈을 갚을 수 있는 제도를 만들라는 것이다. 나라가 국민들 살려주는건 당
연하지... 하지만 국민도 자기목숨 살려준 정부와 다른 국민에게 할 일이 있어야 할 것이
아닌가? 세금을 왕창 부과해서 그 돈질한 혈세를 평생 갚도록 만드는게 어떨까?
그런 제도가 있어야 위험한테 함부로 안 쏘다닐거 아니야...

내가 기독교를 싫어하는건 절대 아니고 나도 기독교인으로서.. 한마디만 더
기독교인들 자제좀 해라... 샬롬 샬롬 하는데... 좀 보기 그렇다.

2007년 7월 7일 토요일

카라잔 황천의 원령 공략법

안녕하세요 이오나 서버 새벽공대 메인탱커 "남자의자신감(캘:Airokmc)" 입니다.
오늘 처음 황천의 원령을 만났는데 저도 잘 모르겠고, 다른분들도 우왕자왕 하시는것 같아서
여러 공략사이트를 보고 연구한 결과로 나온 공략법을 올립니다.

어느 공대, 어느 공략이건 가장 중요한건 팀웍입니다.

그럼 진영을 살펴보겠습니다.(그림이 잘 안보일 경우 클릭하셔서 보면 됩니다.)
사용자 삽입 이미지
기본진영


황천의 원령의 가장 큰 특징은 임의의 3방향에서 적색, 청색, 녹색의 광선을 쏘는데
각 광선마다 특징이 있습니다.

플레이어
적색 : 체력을 증가시키며 공격력을 향상시킵니다. 위협수준 1순위
         중첩될수록 체력이 감소합니다.
청색 : 마법효과와 입는 데미지를 증가시킵니다.
         중첩될수록 피해량 증가, 치유효과 감소
녹색 : 치유효과 증가, 중첩될수록 마나 감소

황천의원령
적색 : 피해량 감소
청색 : 공격량 증가
녹색 : 체력 회복

이광선은 황천의원령이 맞으면 공략에 실패할수 있기 때문에 플레이어가 막습니다.(이하 광선탱킹)

우리 공대 구성으로 파티를 짜봤습니다.
1파 : 전사, 드루이드, 성기사, 도적(적색)
2파 : 암사제, 흑마법사1, 마법사(청색, 녹색)
3파 : 사냥꾼, 흑마법사2, 힐사제(녹색, 청색)

황천의 원령의 공격 패턴은 시작하면 50초간 광선, 30초간 광역, 다시 50초간 광선
50초간 광선을 때 광선탱킹을 하고, 광역일때 방 구석으로 도망쳐서 광역 마법을 맞지 않도록 합니다.

첫번째 1파에서 전사가 적색, 2파에서 암사제가 청색, 3파에서 사냥꾼이 녹색 광선탱킹을합니다. 그리고 이 광선탱킹을 하는도중 광선에 대한 디버프가 중첩되는데 약 25~30 개정도 중첩될경우 다른 플레이어랑 광선탱킹 교체를 합니다. 교체하는 방법은 다음과 같습니다.
사용자 삽입 이미지

탱 교체 방법


1번이 탱킹하고 있을때 2번이 광선과 1번탱커 사이로 끼어듭니다. 그래서 광선을 막은뒤에
1번이 원래 자리에서 나옵니다. 꼭 1번이 자리를 비켜야 할 필요는 없습니다.

탱교체가 되면 그동안 광선을 맡았던 첫번째 광선 탱커는 90초 짜리 광선 디버프가 걸리는데 그 디버프 동안은 똑같은 광선을 탱킹하지 못합니다. 그래서 두번째 턴에서는 다른 색깔광선을 탱킹해야 합니다.

이런식으로 교체가 이루어 집니다.
그래서 한턴(광역탐 전)에 단 한번의 교체가 이루어 집니다. 한번의 교체가 이루어지기 위해서는 각 탱커가 디버프를 25~30까지 중첩 시켜야 가능합니다.

두번째 탱커가 들어와서 광선탱킹이 끝날때 즈음 되면 황천의 원령이 추방당하면서
광역타임에 들어갑니다. 그때는 황천의 용숨결이라는 강한 마법을 쓰는데 그걸 피하기 위해서는 방 구석으로 대피하시면 되겠습니다.
사용자 삽입 이미지

대피 요령

30초 동안 추방당한뒤에 두번째 턴이 시작됩니다.
두번째 턴에서는 1파는 적색을 유지하고, 2파는 청색에서 녹색, 3파는 녹색에서 청색광석을 탱킹합니다. 그 이유는 앞에 설명드렸다시피 90초짜리 디버프 덕분이겠죠.

1파는 왜 적색탱킹을 유지하냐면 적색광선은 위협수준 1순위 입니다. 그래서 그나마 탱킹이
가능한 클래스로 구성했습니다. 1파외의 다른 파티원이 적색광선을 맞을 경우 한방 다이할 가능성이 높습니다.
두번째 턴에서도 순서대로 탱커를 교체해가면서 광선탱킹을 하면되겠습니다.

전투중 탱킹 시간과 디버프 시간을 다음 그림에서 표현했습니다.
반드시 확대해서 보시기 바랍니다.
사용자 삽입 이미지


물론 제가 생각한 대로 100% 돌아갈리 없겠지만, 이정도 되면 탱킹시간과 디버프 시간을 잘 요리해서 어느정도 대처가 될것으로 보입니다.

두번째 턴이 끝나면 다시 첫번째 턴에서 했던 방식으로 하면 되겠습니다.

여기서 문제는 광선방향이 광역타임 이후로 랜덤하게 변하는것인데, 광선이 나오기전에
주변에 소환의 문이 열립니다. 그 소환의 문이 광선색과 동일 하기 때문에, 소환의 문이
열릴 때 색깔을 보고 탱킹 준비를 해주시면 되겠습니다.

덧붙여서 뎀딜은 미친듯이 해도 됩니다. 그리고 푸른광석을 맞고 있는 딜러는 체력 저하가
심하기 때문에 힐을 열심히 해주셔야 됩니다.

황천의 원령은 모든걸 다 제쳐두고서라도 광선탱킹이 제대로 되지 않는다면 아무리 힐좋고,
뎀딜 좋은 공대도 반드시 실패합니다.

허접한 공략이지만 잘 숙지해서 황천의원령을 쓰러뜨리는 기쁨을 같이 누렸으면 좋겠습니다.

이상 이오나 새벽 공대 메인탱커 "남자의자신감(캘:Airokmc)" 였습니다.

2007년 6월 24일 일요일

컴플렉스를 대할때

무슨 말을 해도 다 받아줄 것 같은 성인군자도 화를 낼 때가 있다. 돌부처 같은 사람도 어떤 부분을 건드리면 견디지 못하는 경우가 있다. 사람이라면 누구나 절대로 자극받고 싶지 않은 민감한 부분, 즉 그사람만의 컴플렉스를 갖고 있다.
한비자(韓非子)는 군주를 설득하는 과정의 어려움을 다룬 <세난> 편에서 상대의 치부를 건드리면 결코 그를 설득할 수 없음을 역린지화(逆鱗之禍)로 경고 했다.

"용이란 원래 순한 동물이다. 길을 잘 들이면 사람이 타고 다닐 수도 있다. 하지만 목 근처의 길이가 한 자나 되는 거꾸로 난 비늘, 역린을 건드리면 절대로 안된다. 용은 이것을 건드리는 자를 반드시 죽여버린다. 군주에게도 이런 역린이 있으니 절대로 이 역린을 건드려서는 안된다."

군주만 역린을 갖고 있는 것이 아니다. 사람이라면 누구나 자기 나름의 역린을 가지고 있다. 역린이란 요즘 말로 표현하면 그 사람의 핵심 컴플렉스이다. 어떤 사람과 좋은 관계를 원한다면 자극 받고 싶어하지 않는 그사람의 역린이 무엇인지를 헤아려야 한다. 아무리 허물없는 사이라도 그 사람의 역린을 건드리면 안된다.

2007년 6월 14일 목요일

iPAQ HX4700 에 리눅스 설치하기 #3

준비물

이 글은 나의 실험과 같이 쓰여지기 때문에 좀 빨리 써질 수도 있고 늦게 써질 수도 있다. 하지만 위험(?)을 공유한다는점에서 서로 만족했으면 한다.

어떤 작업을 하기위해선 언제나 준비물이 필요하다. iPAQ 에 리눅스를 올릴때도 자질구래한 준비물이 필요하다.

1. iPAQ hx4700
    이건 당연히 필요하다. 없으면 http://www.handhelds.org 에 가서 호환성 높은 다른 PDA
    를 준비해도 상관은 없다.

2. Serial+USB Sync Cable
    리눅스 포팅을 한번이라도 해본 사람이면 이게 왜 필요한지 알거다.
    특히 iPAQ의 경우 제품을 구입할때 USB 싱크 케이블은 들어 있지만, Serial  케이블은 포
    함되어 있지 않다. Serial 케이블은 HP 홈페이지에 가면 악세사리로 나와있는데 팔지는 않
    는다. 본 글에서는 직접 제작하는 방법에 대해서 알아보겠다.

3. SD card 256M 이상
    일반적인 임베디드 리눅스 포팅에서는 JTAG 을 이용하여 부트로더를 올리는데 iPAQ 의
    경우  JTAG 을 직접 액세스 할 수 없기 때문에, iPAQ 에 실려 있는 HTC Bootloader 에서
    SD 카드를 통해서 부트로더를 올린다.

4. 공CD
    iPAQ 사용계약에 보면 iPAQ 에 다른 OS 를 설치하다가 발생하는 문제는 보증이 안된다고
    나와 있다. 그래서 WinCE 이미지를 유지하고 있어야 한다. 매우 중요하다. 만약에 WinCE
    이미지를 분실해서 발생하는 문제는 나도 handhelds.org 도 책임지지 않는다. 이미지 백
    업과 복구 방법은 이후에 천천히 설명 하도록한다.

5. 리눅스가 설치된 PC
    나는 redhat 9 을 설치했다. 왜냐고? 이때까지 쓰던거니깐... 서로 편한 리눅스를 설치하면
    될 것 같다.

6. 마음의 준비
    이 과정을 수행하다가 PDA 롬을 날려먹는건 100% 본인의 책임이다. 나도 handhelds.org
    도 책임지지 않는다. 시작하기 전에 신중히 생각하라...

!! 자 이정도 준비 되었으면 작업을 시작해도 될것 같다. 다음 글에서는 Serial 과 USB 를 동시에 지원하는 케이블을 만들어 보기로 하자.

iPAQ HX4700 에 리눅스 설치하기 #2

임베디드 리눅스 설치 순서  

이 글을 어느정도 실습 보드를 다뤄본 사람을 대상으로 쓰여져 있다. 하지만 대강적인 지식이 있어도 이해할 수 있도록 어느정도 기본은 짚고 넘어가보자.

일반적인 임베디드 리눅스 설치순서는 크게 다음과 같다.

1. HOST PC 에 리눅스 설치
2. 임베디드 리눅스용 부트로더 컴파일
3. JTAG(Joint test action group) 을 이용하여 flash 에 부트로더를 flash 에 업로드
4. 임베디드 리눅스 커널 컴파일
5. 파일시스템 준비
6. 부트로더에서 lan 또는 serial 을 이용하여 커널 업로드
7. 파일시스템 업로드

내가 쓰는 글을 읽을려면 위의 과정정도는 머릿속에 있어야 하고, 왜? 하는지도 반드시 알아야 한다. 위의 과정이 생소하다고 생각하는 사람은 다른 글이나 웹을 참고해서 반드시 숙지하기 바란다.

아는 사람들도 여건이 된다면 실습을 다시 해보고, 한번더 공부해라...
왜냐고? 중요하니깐... 그렇다고 해서 iPAQ 이 위와 동일한 순서를 따르는건 절대 아니다.

iPAQ HX4700 에 리눅스 설치하기 #1

iPAQ 에 리눅스 설치하기

현재 많은 임베디드 시스템 실습 보드가 나와 있는데, 이놈의 저가형 보드들이 실제 적용을 할려면 제대로 되지 않는것들이 너무 많다. 특히, 저전력 관련 실험이나, 주변장치 제어 등의 실험은 아예 지원자체를 않하거나 보드를 설계할때부터 고려되지 않는다.
물론 일반 PDA 가 지원하는 주변장치 제어, 저전력 관련 기능 등을 fully 지원하는 보드도 있다. 하지만 이런장비는 나같은 돈없는 학생이 만지기엔 너무나 비싼장비이다.
그래서 진짜 임베디드 리눅스를 깊게 파보고 싶고, 실제 적용 가능할 상품을 실험하는 사람들은 시중에 판매되는 PDA 를 이용하는데... 이것역시 쉽지 않은일이다. 대부분의 시판되는 PDA 는 WinCE(Windows Mobile) 이 깔린 장치가 대부분이고, 그나마 리눅스가 깔린 장치는 특정 기능에 한정되어 있기 때문이다.
나도 공부를 하면서 이런저런 실험을 하는데, 실습보드가 너무 마음에 들지 않아서 결국 PDA 에서 실험하기로 마음먹고, iPAQ 에 리눅스를 설치하기로 했다.
이 글을 쓰는 목적은 나같이 PDA 에 리눅스를 올리고 싶은데, 어떻게 하는지 몰라서... 또는 어디서 정보를 찾아야 하는지 몰라서 헤메는 사람에게 조금이라도 도움을 주고 정보를 나누고자 함이다.

이 글은 http://www.handhelds.org 에서 많은 정보를 참조했으며, HP iPAQ HX4700 을 기준으로 연재된다.(잘 쓸수 있을까??)

왜 HX4700 을 기준으로 했을까...

다음은 http://www.handhelds.org/moin/moin.cgi/HpIpaqHx4700 에서 발췌한 테이블이다.

Hardware support status code: A+

Component Status Comments

Boot process (all ticks required for D status)
Boot process (./)

Boot-critical hardware (all ticks required for C status)
Basic hardware (./)
USB to host (./) RNDIS now works too
SD-MMC/PCMCIA(CF) (./)
Display (./)

Basic PDA hardware/use (all ticks required for B status)
Buttons (./) Cases of rare "stuck key" syndrome reported (due to navpoint)
Touchscreen (./)
Suspend/Resume (./)
Battery control (./)
APM status (./)
Backlight (./)
GUI launching - GPE/OPIE (./) / (./)

Advanced PDA hardware/use (all ticks required for A status)
Sound (./)
Flash memory (./)
IrDA (./)
LEDs (./)
Bootloader (./)

Full hardware support (all ticks required for A+ status)
Bluetooth (./)
Wifi (./) Has suspend/resume issues, no WPA yet


위에서 보다시피 HX4700 에서 작동하는 커널 상태가 매우 좋고, 호환성이 뛰어나다 관련 정보를 찾아보면 다른 PDA 에 비해서 점수가 높다(A+)
물론 HX4700 이 없다면 다른 PDA 에 올려볼려는 시도를 할 수는 있지만 나같은 경우 hx2750 에 올리다가 커널 상태가 너무 좋지 않아서 포기했다. 자신이 커널을 이리저리 쥐어짜고 뜯어고칠 능력이 있다면 다른 PDA 를 써도 상관없다.. 그런 능력이 있다면 이 브라우져의 창을 닫고 http://www.handhelds.org 로 바로 가길 바란다.


2007년 5월 22일 화요일

Starcraft2 Demo Movie


10년만의 스타크래프 부활이다...

우리나라의 게임방 산업을 활성화 시키고, e-sport 를 탄생시킨
인류역사에 길이 남을 게임 Starcraft...

아마 국제적인 타임캡슐에도 들어갈만한 게임인것 같다.

그런 스타크래프트의 후속작이 한국 World Wide Invitational 에서 공개되었다.
스타크래프트의 유저중에 압도적인 비율이 한국에 몰려 있는걸 감안해서인지

한국에서 최초 발표를 하고... 동영상의 자막이나 음성등도 모두 한국어다(-O-)

플레이 동영상을 보니 워크래프트3처럼 3D 인데 반해

워크래프트의 가장 단점으로 지적된 속도감이 없다는것은 배제 된 듯 하다...
하나하나 움직이는걸 보니 엄청난 노력을 기울인것 같은데

과연 기대대로 걸작이 탄생할것인지...

To make "command prompt here" function

  1. Open Windows Explorer
  2. Choose ToolsFolder Options...
  3. Switch to the File Types tab
  4. Select Folder from the list and press the Advanced button.
  5. Choose New
  6. Give it a nice name like "Command Prompt Here" and the application c:\windows\system32\cmd.exe /K cd "%1"
  7. OK, OK and OK to save it.

2007년 4월 9일 월요일

Uncompressed wave file 에서 정보 추출(VB)

비주얼 베이식에서 웨이브 정보 추출

[CODE type=vb] Public Type wave_header wavRIFFChunk As String * 4 wavSize As Long wavWaveChunk As String * 4 wavFMTChunk As String * 4 wavFormatSize As Long wavPCMFormatFlag As Integer wavChannel As Integer wavSampleRate As Long wavSampleRatePerSec As Long wavPerSecScale As Integer wavBits As Integer wavDataChunk As String * 4 wavDataSize As Long End Type Open txtFile1.Text For Binary As #1 Get #1, , openFile1 If openFile1.wavPCMFormatFlag <> 1 Then MsgBox "표준 PCM 웨이브 파일이 아닙니다.", vbOKOnly + vbInformation, "확인" Close #1 txtFile1.Text = "" Exit Sub End If MCI.Command = "stop" MCI.Command = "close" tinfo = "RIFF Chunk : " & openFile1.wavRIFFChunk & vbCrLf & _ "Size : " & openFile1.wavSize & vbCrLf & _ "Wave Chunk : " & openFile1.wavWaveChunk & vbCrLf & _ "FMT Chunk : " & openFile1.wavFMTChunk & vbCrLf & _ "Format Size : " & openFile1.wavFormatSize & vbCrLf & _ "PCM Format Flag : " & openFile1.wavPCMFormatFlag & vbCrLf & _ "Channels : " & openFile1.wavChannel & vbCrLf & _ "Sample Rate : " & openFile1.wavSampleRate & vbCrLf & _ "Sample Rate/sec : " & openFile1.wavSampleRatePerSec & vbCrLf & _ "Per sec Scale : " & openFile1.wavPerSecScale & vbCrLf & _ "Bits per Sample : " & openFile1.wavBits & vbCrLf & _ "Data Chunk : " & openFile1.wavDataChunk & vbCrLf & _ "Data Size : " & openFile1.wavDataSize lblInformation1.Caption = tinfo zNumSample1 = openFile1.wavDataSize / (openFile1.wavChannel * (openFile1.wavBits / 8)) lblWating1.Visible = True DoEvents ReDim WaveData1(openFile1.wavChannel, zNumSample1) 'reading data For i = 0 To zNumSample1 - 1 For j = 0 To openFile1.wavChannel - 1 If openFile1.wavBits = 8 Then Get #1, , sdata8 WaveData1(j, i) = sdata8 Else Get #1, , sdata16 WaveData1(j, i) = sdata16 End If Next Next lblWating1.Visible = False Close #1 [/CODE]

Welcome to Hardball3 !!!

사용자 삽입 이미지

기억하는가? Welcome to Hardball3  초등학생때 나온 게임인데..
화면에 보다시피 Al Michaels Announces 라는 문구 처럼
최초의 실황 중계 야구 게임이다.

워낙에 어콜레이드가 유명한 게임회사라 게임을 즐기는 사람들이 많았지만
난 중계가 너무 신기해서 중계를 들을려고 게임을 했었다.
물론 무슨말인지는 몰랐지만 컴퓨터에서 그런 소리가 나오는게 너무 신기했다.

그 전에 나온 야구 게임과는 다르게 엄청난 설정의 자세함과
조작의 간편함 때문에 많은 사랑을 받았던 게임이다.

사용자 삽입 이미지

친구들과 모여서 작은 키보드에 손을 감추고 키를 눌러대던 생각이 간절하다.

이 시절의 대부분의 도스용 게임에는 복사방지 기술이 없었기 때문에
"암호표" 라는것이 존재 했고, Hardball 3 역시 예외는 아니었다.

지금은 구해볼수 없지만... 동그란 원판 세개로 이루어진 암호표가 기억난다.
친구가 구입한 이게임을 복사하고 암호표까지 종이로 만들면서
몇시간을 보낸적이 있다.

그때 생각하면.. 참 그런것에 대해 집착했구나 하는 생각도 많이 든다.

그 후에 어콜레이드는 HardBall4 에서 실사 그래픽으로 한번더 성공을 거두고...
HardBall 5 에서는 거의 졸작질을 하다가...

윈도우로 변한 게임환경에 적응하지 못하고 EA Triple Play 에 밀려
역사의 뒤안길로 사라지게 된다.

2007년 4월 6일 금요일

Band of brothers

사용자 삽입 이미지

내가 생각하는 최고의 전쟁 드라마...

Band of brothers 라는 제목의 의미는 직역하자면 형재의 끈 정도로 해석할 수 있지만
드라마 내용을 보니.. "전우애" 라고 할 수 있을것 같다.

라이언 일병 구하기의 확장판 정도로 생각된다.

어떤 사람은 군인에 대해서 막연히 멋있다 라고 생각 할 수 도 있고,
어떤 사람은 군인이면 아무것도 모르고 싫다고 생각할 수 도 있는데...

이 드라마를 보면 군인이 해야 할 일들에 대해서 너무도 자세히 나왔고
군인도 하나의 인간이라는것을 잘 묘사해놓았다.

누구나 본다면 한번쯤 감동을 받을만한 드라마...

2007년 4월 3일 화요일

Uncompressed wave file 에서 정보 추출

압축되지 않은 wave 파일에서 header 정보를 가져오는 소스


[CODE] #include typedef struct { char wavRIFFChunk[4]; long wavSize; char wavWAVEChunk[4]; char wavFMTChunk[4]; long wavFormatSize; short wavPCMFormatFlag; short wavChannel; long wavSampleRate; long wavSampleRatePerSec; short wavPerSecScale; short wavBits; char wavDataChunk[4]; long wavDataSize; }wav_header; int main(int argc, char** argv) { wav_header in_wav; FILE* fp; char pBuffer[5]; if(argc != 2) { printf("usage : getwavinfo.exe [wav_file]\n"); return 1; } if((fp = fopen(argv[1], "rb")) == NULL) { printf("file open error : %s\n", argv[1]); return 1; } fread(&in_wav, sizeof(wav_header), 1, fp); fclose(fp); strncpy(pBuffer, in_wav.wavRIFFChunk, 4); pBuffer[4] = 0; printf("Riff Chunk : %s\n", pBuffer); printf("Size : %d byte(s)\n", in_wav.wavSize); strncpy(pBuffer, in_wav.wavWAVEChunk, 4); pBuffer[4] = 0; printf("Wave Chunk : %s\n", pBuffer); strncpy(pBuffer, in_wav.wavFMTChunk, 4); pBuffer[4] = 0; printf("FMT Chunk : %s\n", pBuffer); printf("Format Size : %d\n", in_wav.wavFormatSize); printf("PCM Format Flag : %d\n", in_wav.wavPCMFormatFlag); printf("Channels : %d\n", in_wav.wavChannel); printf("Sample Rate : %d\n", in_wav.wavSampleRate); printf("Sample Rate Per Second : %d\n", in_wav.wavSampleRatePerSec); printf("Per Second Scale : %d\n", in_wav.wavPerSecScale); printf("Bits Per Sample : %d\n", in_wav.wavBits); strncpy(pBuffer, in_wav.wavDataChunk, 4); pBuffer[4] = 0; printf("Data Chunk : %s\n", pBuffer); printf("Data Size : %d\n", in_wav.wavDataSize); return 0; } [/CODE]

Wave File Format

Table of Contents

Overview

The Wave file format is Windows' native file format for storing digital audio data. It has become one of the most widely supported digital audio file formats on the PC due to the popularity of Windows and the huge number of programs written for the platform. Almost every modern program that can open and/or save digital audio supports this file format, making it both extremely useful and a virtual requirement for software developers to understand. The following specification gives a detailed description of the structure and inner workings of this format.

Data Formats

Since the Wave file format is native to Windows and therefor Intel processors, all data values are stored in Little-Endian (least significant byte first) order.

Strings
Wave files may contain strings of text for specifying cue point labels, notes, etc. Strings are stored in a format where the first byte specifies the number of following ASCII text bytes in the string. The following bytes are of course the ASCII character bytes that make up the text string. Pascal programmers will notice that this is the same format used for Pascal strings.

7 'e' 'x' 'a' 'm' 'p' 'l' 'e'
Wave String Format Example

File Structure

Basic Wave File Layout

Chunk ID "RIFF"
Chunk Data Size
RIFF Type ID "WAVE"
Chunk ID "fmt "
Chunk Data Size
Sample Format Info
Chunk ID "data"
Chunk Data Size
Digital Audio Samples

Chunk Header
Chunk Data Bytes

Wave files use the standard RIFF structure which groups the files contents (sample format, digital audio samples, etc.) into separate chunks, each containing it's own header and data bytes. The chunk header specifies the type and size of the chunk data bytes. This organization method allows programs that do not use or recognize particular types of chunks to easily skip over them and continue processing following known chunks. Certain types of chunks may contain sub-chunks. For example, in the diagram to the right, you can see that the "fmt " and "data" chunks are actually sub-chunks of the "RIFF" chunk.

One tricky thing about RIFF file chunks is that they must be word aligned. This means that their total size must be a multiple of 2 bytes (ie. 2, 4, 6, 8, and so on). If a chunk contains an odd number of data bytes, causing it not to be word aligned, an extra padding byte with a value of zero must follow the last data byte. This extra padding byte is not counted in the chunk size, therefor a program must always word align a chunk headers size value in order to calculate the offset of the following chunk.

Wave File Header - RIFF Type Chunk

Wave file headers follow the standard RIFF file format structure. The first 8 bytes in the file is a standard RIFF chunk header which has a chunk ID of "RIFF" and a chunk size equal to the file size minus the 8 bytes used by the header. The first 4 data bytes in the "RIFF" chunk determines the type of resource found in the RIFF chunk. Wave files always use "WAVE". After the RIFF type comes all of the Wave file chunks that define the audio waveform.

Offset Size Description Value
0x00 4 Chunk ID "RIFF" (0x52494646)
0x04 4 Chunk Data Size (file size) - 8
0x08 4 RIFF Type "WAVE" (0x57415645)
0x10
Wave chunks
RIFF Type Chunk Values

Wave File Chunks

There are quite a few types of chunks defined for Wave files. Many Wave files contain only two of them, specifically the Format Chunk and the Data Chunk. These are the two chunks needed to describe the format of the digital audio samples and the samples themselves. Although it is not required by the official Wave file specification, it is good practice to place the Format Chunk before the Data Chunk. Many programs expect the chunks to be stored in this order and it is more sensible when streaming digital audio from a slow, linear source such as the Internet. If the format were to come after the data, all of the data and then the format would have to be streamed before playback could start correctly.

All RIFF Chunks and therefore Wave Chunks are stored in the following format. Notice that even the above mentioned RIFF Type Chunk conforms to this format.

Offset Size Description
0x00 4 Chunk ID
0x04 4 Chunk Data Size
0x08 Chunk Data Bytes
RIFF Chunk Format

The rest of this document goes through the different types of Wave chunks, describing the format of their data bytes and what they mean. You can use the table of contents at the beginning of this document to help find the chunk type you are interested in.

Format Chunk - "fmt "

The format chunk contains information about how the waveform data is stored and should be played back including the type of compression used, number of channels, sample rate, bits per sample and other attributes.

Offset Size Description Value
0x00 4 Chunk ID "fmt " (0x666D7420)
0x04 4 Chunk Data Size 16 + extra format bytes
0x08 2 Compression code 1 - 65,535
0x0a 2 Number of channels 1 - 65,535
0x0c 4 Sample rate 1 - 0xFFFFFFFF
0x10 4 Average bytes per second 1 - 0xFFFFFFFF
0x14 2 Block align 1 - 65,535
0x16 2 Significant bits per sample 2 - 65,535
0x18 2 Extra format bytes 0 - 65,535
0x1a
Extra format bytes *
Wave Format Chunk Values, * read following text for details

Chunk ID and Data Size
The chunk ID is always "fmt " (0x666D7420) and the size is the size of the standard wave format data (16 bytes) plus the size of any extra format bytes needed for the specific Wave format, if it does not contain uncompressed PCM data. Note the chunk ID string ends with the space character (0x20).

Compression Code
The first word of format data specifies the type of compression used on the Wave data included in the Wave chunk found in this "RIFF" chunk. The following is a list of the common compression codes used today.

Code Description
0 (0x0000) Unknown
1 (0x0001) PCM/uncompressed
2 (0x0002) Microsoft ADPCM
6 (0x0006) ITU G.711 a-law
7 (0x0007) ITU G.711 �-law
17 (0x0011) IMA ADPCM
20 (0x0016) ITU G.723 ADPCM (Yamaha)
49 (0x0031) GSM 6.10
64 (0x0040) ITU G.721 ADPCM
80 (0x0050) MPEG
65,536 (0xFFFF) Experimental
Common Wave Compression Codes

Number of Channels
The number of channels specifies how many separate audio signals that are encoded in the wave data chunk. A value of 1 means a mono signal, a value of 2 means a stereo signal, etc.

Sample Rate
The number of sample slices per second. This value is unaffected by the number of channels.

Average Bytes Per Second
This value indicates how many bytes of wave data must be streamed to a D/A converter per second in order to play the wave file. This information is useful when determining if data can be streamed from the source fast enough to keep up with playback. This value can be easily calculated with the formula:

AvgBytesPerSec = SampleRate * BlockAlign

Block Align
The number of bytes per sample slice. This value is not affected by the number of channels and can be calculated with the formula:

BlockAlign = SignificantBitsPerSample / 8 * NumChannels

Significant Bits Per Sample
This value specifies the number of bits used to define each sample. This value is usually 8, 16, 24 or 32. If the number of bits is not byte aligned (a multiple of 8) then the number of bytes used per sample is rounded up to the nearest byte size and the unused bytes are set to 0 and ignored.

Extra Format Bytes
This value specifies how many additional format bytes follow. It does not exist if the compression code is 0 (uncompressed PCM file) but may exist and have any value for other compression types depending on what compression information is need to decode the wave data. If this value is not word aligned (a multiple of 2), padding should be added to the end of this data to word align it, but the value should remain non-aligned.

Data Chunk - "data"

The Wave Data Chunk contains the digital audio sample data which can be decoded using the format and compression method specified in the Wave Format Chunk. If the Compression Code is 1 (uncompressed PCM), then the Wave Data contains raw sample values. This document explains how an uncompressed PCM data is stored, but will not get into the many supported compression formats.

Wave files usually contain only one data chunk, but they may contain more than one if they are contained within a Wave List Chunk ("wavl").

Offset Length Type Description Value
0x00 4 char[4] chunk ID "data" (0x64617461)
0x04 4 dword chunk size depends on sample length and compression
0x08
sample data
Data Chunk Format

Multi-channel digital audio samples are stored as interlaced wave data which simply means that the audio samples of a multi-channel (such as stereo and surround) wave file are stored by cycling through the audio samples for each channel before advancing to the next sample time. This is done so that the audio files can be played or streamed before the entire file can be read. This is handy when playing a large file from disk (that may not completely fit into memory) or streaming a file over the Internet. The values in the diagram below would be stored in a Wave file in the order they are listed in the Value column (top to bottom).

Time Channel Value
0 1 (left) 0x0053
2 (right) 0x0024
1 1 (left) 0x0057
2 (right) 0x0029
2 1 (left) 0x0063
2 (right) 0x003C
Interlaced Stereo Wave Samples

One point about sample data that may cause some confusion is that when samples are represented with 8-bits, they are specified as unsigned values. All other sample bit-sizes are specified as signed values. For example a 16-bit sample can range from -32,768 to +32,767 with a mid-point (silence) at 0.

As mentioned earlier, all RIFF chunks (including WAVE "data" chunks) must be word aligned. If the sample data uses an odd number of bytes, a padding byte with a value of zero must be placed at the end of the sample data. The "data" chunk header's size should not include this byte.

Fact Chunk - "fact"

A fact chunk stores compression code dependant information about the contents of the Wave file. It is required by all compressed WAVE formats and if the waveform data is contained inside a "wavl" LIST chunk, but is not required for the uncompressed PCM WAVE format files (compression code 1) that contain the waveform data inside a "data" chunk.

Offset Size Description Value
0x00 4 Chunk ID "fact" (0x66616374)
0x04 4 Chunk Data Size depends on format
0x08
Format Dependant Data
Fact Chunk Format

Format Dependant Data
There is currently only one field defined for the format dependant data. It is a single 4-byte value that specifies the number of samples in the waveform data chunk. This value can be used with the Samples Per Second value specified in the format chunk to calculate the waveforms length in seconds.

As new WAVE formats are introduced, the fact chunk will be expanded, appending fields after the defined number of samples field. Applications can use the fact chunk size to determine which fields are present in the chunk.

Wave List Chunk - "wavl"

A wave list chunk is used to specify several alternating "slnt" and "data" chunks. These chunks can help reduce a Wave file's size while specifying audible segments of samples when a stream of digital audio contains several periods of silence.

This type of chunk is considered to be an abuse of the Wave file format by many programmers (including myself) and it's support is not recommended. Also many programs will not recognize this type of chunk, simply ignoring it. This form of compression unnecessarily complicates the structure of a Wave file and could be better implemented in other ways, including the use of several existing compression formats.

Offset Size Description Value
0x00 4 Chunk ID "slnt" (0x736C6E74)
0x04 4 Chunk Data Size depends on size of data and slnt chunks
0x08 List of Alternating "slnt" and "data" Chunks
Wave List Chunk Format

Silent Chunk - "slnt"

A silent chunk is used to specify a segment of silence that will last some duration of samples. It is always contained within a wave list chunk. While this chunk represents silence, it does not necessarily define a zero volume or baseline sample. It actually holds the last sample value present in the preceding data chunk in the wave list chunk. If there is no preceding data chunk in the wave list chunk, a baseline value should be used (127 for 8-bit data, 0 for 16-bit or higher data). This may seem trivial, but if not followed, may cause undesired clicks and pops in the audio signal.

Offset Size Description Value
0x00 4 Chunk ID "slnt" (0x736C6E74)
0x04 4 Chunk Data Size 4
0x08 4 Number of Silent Samples 0 - 0xFFFFFFFF
Silent Chunk Format

Number of Silent Samples
This value specifies the number of silent samples that appear in the waveform at this point in the wave list chunk.

Cue Chunk - "cue "

A cue chunk specifies one or more sample offsets which are often used to mark noteworthy sections of audio. For example, the beginning and end of a verse in a song may have cue points to make them easier to find. The cue chunk is optional and if included, a single cue chunk should specify all cue points for the "WAVE" chunk. No more than one cue chunk is allowed in a "WAVE" chunk.

Offset Size Description Value
0x00 4 Chunk ID "cue " (0x63756520)
0x04 4 Chunk Data Size depends on Num Cue Points
0x08 4 Num Cue Points number of cue points in list
0x0c
List of Cue Points
Cue Chunk Format

Chunk ID and Data Size
The chunk ID for a cue chunk is always "cue " (0x666D7420). Note that the chunk ID string ends with the space character (0x20). The chunk data size is equal to the size of the Num Cue Points value (4) plus the number of following cue points multiplied by the size of each cue point's data (24). The following formula can be used to calculate a Cue Chunk's data size:

ChunkDataSize = 4 + (NumCuePoints * 24)

Num Cue Points
This value specifies the number of following cue points in this chunk.

List of Cue Points
A list of cue points is simply a set of consecutive cue point descriptions that follow the format described below.

Offset Size Description Value
0x00 4 ID unique identification value
0x04 4 Position play order position
0x08 4 Data Chunk ID RIFF ID of corresponding data chunk
0x0c 4 Chunk Start Byte Offset of Data Chunk *
0x10 4 Block Start Byte Offset to sample of First Channel
0x14 4 Sample Offset Byte Offset to sample byte of First Channel
Cue Point Format

ID
Each cue point has a unique identification value used to associate cue points with information in other chunks. For example, a Label chunk contains text that describes a point in the wave file by referencing the associated cue point.

Position
The position specifies the sample offset associated with the cue point in terms of the sample's position in the final stream of samples generated by the play list. Said in another way, if a play list chunk is specified, the position value is equal to the sample number at which this cue point will occur during playback of the entire play list as defined by the play list's order. If no play list chunk is specified this value should be 0.

Data Chunk ID
This value specifies the four byte ID used by the chunk containing the sample that corresponds to this cue point. A Wave file with no play list is always "data". A Wave file with a play list containing both sample data and silence may be either "data" or "slnt".

Chunk Start
The Chunk Start value specifies the byte offset into the Wave List Chunk of the chunk containing the sample that corresponds to this cue point. This is the same chunk described by the Data Chunk ID value. If no Wave List Chunk exists in the Wave file, this value is 0. If a Wave List Chunk exists, this is the offset into the "wavl" chunk. The first chunk in the Wave List Chunk would be specified with a value of 0.

Block Start
The Block Start value specifies the byte offset into the "data" or "slnt" Chunk to the start of the block containing the sample. The start of a block is defined as the first byte in uncompressed PCM wave data or the last byte in compressed wave data where decompression can begin to find the value of the corresponding sample value.

Sample Offset
The Sample Offset specifies an offset into the block (specified by Block Start) for the sample that corresponds to the cue point. In uncompressed PCM waveform data, this is simply the byte offset into the "data" chunk. In compressed waveform data, this value is equal to the number of samples (may or may not be bytes) from the Block Start to the sample that corresponds to the cue point.

Playlist Chunk - "plst"

The playlist chunk specifies the play order of a series of cue points. The cue points are defined in the cue chunk, somewhere else in the file. A playlist consists of an array of segments, each containing information about what sample the segment should start playing from, how long the segment is (in samples) and how many times to repeat the segment before moving on to the next segment in the play order.

Offset Size Description Value
0x00 4 Chunk ID "plst" (0x736C6E74)
0x04 4 Chunk Data Size num segments * 12
0x08 4 Number of Segments 1 - 0xFFFFFFFF
0x0a
List of Segments
Playlist Chunk Format

Number of Segments
This value specifies the number of following segments in the playlist chunk.

List of Segments
A list of segments is simply a set of consecutive segment descriptions that follow the format described below. The segments do not have to be in any particular order because each segments associated cue point position is used to determine the play order.

Offset Size Description Value
0x00 4 Cue Point ID 0 - 0xFFFFFFFF
0x04 4 Length (in samples) 1 - 0xFFFFFFFF
0x08 4 Number of Repeats 1 - 0xFFFFFFFF
Segment Format

Cue Point ID
The Cue Point ID specifies the starting sample for this segment by providing the value of a Cue Point defined in the Cue Point List. The ID that associates this segment with a Cue Point must be unique to all other segment Cue Point IDs.

Length
The Segment Length specifies the number of samples to play/loop from the starting sample defined by the associated Cue Point.

Number of Repeats
The number of repeats determines how many times this segment should be looped before playback should continue onto the next segment.

Associated Data List Chunk - "list"

An associated data list chunk is used to define text labels and names which are associated with the cue points to provide each text label or name a position.

Offset Size Description Value
0x00 4 Chunk ID "list" (0x6C696E74)
0x04 4 Chunk Data Size depends on contained text
0x08 4 Type ID "adtl" (0x6164746C)
0x0c
List of Text Labels and Names
Associated Data List Chunk Format

Type ID
The type ID is used to identify the type of associated data list and is always "adtl".

List of Text Labels and Names
The list of text labels and names is a list of assorted chunks that define text in different ways. The three main chunk types that are used in WAVE files are the Label Chunk, Note Chunk and Labeled Text Chunk.

Label Chunk - "labl"

The label chunk is always contained inside of an associated data list chunk. It is used to associate a text label with a Cue Point. This information is often displayed next to markers or flags in digital audio editors.

Offset Size Description Value
0x00 4 Chunk ID "labl" (0x6C61626C)
0x04 4 Chunk Data Size depends on contained text
0x08 4 Cue Point ID 0 - 0xFFFFFFFF
0x0c
Text
Label Chunk Format

Cue Point ID
The Cue Point ID specifies the sample point that corresponds to this text label by providing the ID of a Cue Point defined in the Cue Point List. The ID that associates this label with a Cue Point must be unique to all other label Cue Point IDs.

Text
The text is a null terminated string of characters. If the number of characters in the string is not even, padding must be appended to the string. The appended padding is not considered in the label chunk's chunk size field.

Note Chunk - "note"

The label chunk is always contained inside of an associated data list chunk. It is used to associate a text comment with a Cue Point. This information is stored in an identical fashion to the labels in the label chunk.

Offset Size Description Value
0x00 4 Chunk ID "note" (0x6E6F7465)
0x04 4 Chunk Data Size depends on contained text
0x08 4 Cue Point ID 0 - 0xFFFFFFFF
0x0C
Text
Label Chunk Format

Cue Point ID
The Cue Point ID specifies the sample point that corresponds to this text comment by providing the ID of a Cue Point defined in the Cue Point List. The ID that associates this label with a Cue Point must be unique to all other note chunk Cue Point IDs.

Text
The text is a null terminated string of characters. If the number of characters in the string is not even, padding must be appended to the string. The appended padding is not considered in the note chunk's chunk size field.

Labeled Text Chunk - "ltxt"

The labeled text chunk is always contained inside of an associated data list chunk. It is used to associate a text label with a region or section of waveform data. This information is often displayed in marked regions of a waveform in digital audio editors.

Offset Size Description Value
0x00 4 Chunk ID "ltxt" (0x6C747874)
0x04 4 Chunk Data Size depends on contained text
0x08 4 Cue Point ID 0 - 0xFFFFFFFF
0x0c 4 Sample Length 0 - 0xFFFFFFFF
0x10 4 Purpose ID 0 - 0xFFFFFFFF
0x12 2 Country 0 - 0xFFFF
0x14 2 Language 0 - 0xFFFF
0x16 2 Dialect 0 - 0xFFFF
0x18 2 Code Page 0 - 0xFFFF
0x1A
Text
Label Chunk Format

Cue Point ID
The Cue Point ID specifies the starting sample point that corresponds to this text label by providing the ID of a Cue Point defined in the Cue Point List. The ID that associates this label with a Cue Point must be unique to all other note chunk Cue Point IDs.

Sample Length
The sample length defines how many samples from the cue point the region or section spans.

Purpose ID
The purpose field specifies what the text is used for. For example a value of "scrp" means script text, and "capt" means close-caption. There are several more purpose IDs, but they are meant to be used with other types of RIFF files (not usually found in WAVE files).

Country, Language, Dialect and Code Page
These fields are used to specify information about the location and language used by the text and are typically used for queries to obtain information from the operating system.

Text
The text is a null terminated string of characters. If the number of characters in the string is not even, padding must be appended to the string. The appended padding is not considered in the note chunk's chunk size field.

Sampler Chunk - "smpl"

Offset Size Description Value
0x00 4 Chunk ID "smpl" (0x736D706C)
0x04 4 Chunk Data Size 36 + (Num Sample Loops * 24) + Sampler Data
0x08 4 Manufacturer 0 - 0xFFFFFFFF
0x0C 4 Product 0 - 0xFFFFFFFF
0x10 4 Sample Period 0 - 0xFFFFFFFF
0x14 4 MIDI Unity Note 0 - 127
0x18 4 MIDI Pitch Fraction 0 - 0xFFFFFFFF
0x1C 4 SMPTE Format 0, 24, 25, 29, 30
0x20 4 SMPTE Offset 0 - 0xFFFFFFFF
0x24 4 Num Sample Loops 0 - 0xFFFFFFFF
0x28 4 Sampler Data 0 - 0xFFFFFFFF
0x2C
List of Sample Loops
Sampler Chunk Format

Manufacturer
The manufacturer field specifies the MIDI Manufacturer's Association (MMA) Manufacturer code for the sampler intended to receive this file's waveform. Each manufacturer of a MIDI product is assigned a unique ID which identifies the company. If no particular manufacturer is to be specified, a value of 0 should be used.

The value is stored with some extra information to enable translation to the value used in a MIDI System Exclusive transmission to the sampler. The high byte indicates the number of low order bytes (1 or 3) that are valid for the manufacturer code. For example, the value for Digidesign will be 0x01000013 (0x13) and the value for Microsoft will be 0x30000041 (0x00, 0x00, 0x41). See the MIDI Manufacturers List for a list.

Product
The product field specifies the MIDI model ID defined by the manufacturer corresponding to the Manufacturer field. Contact the manufacturer of the sampler to get the model ID. If no particular manufacturer's product is to be specified, a value of 0 should be used.

Sample Period
The sample period specifies the duration of time that passes during the playback of one sample in nanoseconds (normally equal to 1 / Samplers Per Second, where Samples Per Second is the value found in the format chunk).

MIDI Unity Note
The MIDI unity note value has the same meaning as the instrument chunk's MIDI Unshifted Note field which specifies the musical note at which the sample will be played at it's original sample rate (the sample rate specified in the format chunk).

MIDI Pitch Fraction
The MIDI pitch fraction specifies the fraction of a semitone up from the specified MIDI unity note field. A value of 0x80000000 means 1/2 semitone (50 cents) and a value of 0x00000000 means no fine tuning between semitones.

SMPTE Format
The SMPTE format specifies the Society of Motion Pictures and Television E time format used in the following SMPTE Offset field. If a value of 0 is set, SMPTE Offset should also be set to 0.

Value SMPTE Format
0 no SMPTE offset
24 24 frames per second
25 25 frames per second
29 30 frames per second with frame dropping (30 drop)
30 30 frames per second
SMPTE Format Values

SMPTE Offset
The SMPTE Offset value specifies the time offset to be used for the synchronization / calibration to the first sample in the waveform. This value uses a format of 0xhhmmssff where hh is a signed value that specifies the number of hours (-23 to 23), mm is an unsigned value that specifies the number of minutes (0 to 59), ss is an unsigned value that specifies the number of seconds (0 to 59) and ff is an unsigned value that specifies the number of frames (0 to -1).

Sample Loops
The sample loops field specifies the number Sample Loop definitions in the following list. This value may be set to 0 meaning that no sample loops follow.

Sampler Data
The sampler data value specifies the number of bytes that will follow this chunk (including the entire sample loop list). This value is greater than 0 when an application needs to save additional information. This value is reflected in this chunks data size value.

List of Sample Loops
A list of sample loops is simply a set of consecutive loop descriptions that follow the format described below. The sample loops do not have to be in any particular order because each sample loop associated cue point position is used to determine the play order. The sampler chunk is optional.

Offset Size Description Value
0x00 4 Cue Point ID 0 - 0xFFFFFFFF
0x04 4 Type 0 - 0xFFFFFFFF
0x08 4 Start 0 - 0xFFFFFFFF
0x0C 4 End 0 - 0xFFFFFFFF
0x10 4 Fraction 0 - 0xFFFFFFFF
0x14 4 Play Count 0 - 0xFFFFFFFF
Sample Loop Format

Cue Point ID
The Cue Point ID specifies the unique ID that corresponds to one of the defined cue points in the cue point list. Furthermore, this ID corresponds to any labels defined in the associated data list chunk which allows text labels to be assigned to the various sample loops.

Type
The type field defines how the waveform samples will be looped.

Value Loop Type
0 Loop forward (normal)
1 Alternating loop (forward/backward, also known as Ping Pong)
2 Loop backward (reverse)
3 - 31 Reserved for future standard types
32 - 0xFFFFFFFF Sampler specific types (defined by manufacturer)
Loop Type Values

Start
The start value specifies the byte offset into the waveform data of the first sample to be played in the loop.

End
The end value specifies the byte offset into the waveform data of the last sample to be played in the loop.

Fraction
The fractional value specifies a fraction of a sample at which to loop. This allows a loop to be fine tuned at a resolution greater than one sample. The value can range from 0x00000000 to 0xFFFFFFFF. A value of 0 means no fraction, a value of 0x80000000 means 1/2 of a sample length. 0xFFFFFFFF is the smallest fraction of a sample that can be represented.

Play Count
The play count value determines the number of times to play the loop. A value of 0 specifies an infinite sustain loop. An infinite sustain loop will continue looping until some external force interrupts playback, such as the musician releasing the key that triggered the wave's playback. All other values specify an absolute number of times to loop.

Instrument Chunk - "inst"

The instrument chunk is used to describe how the waveform should be played as an instrument sound. This information is useful for communicating musical information between sample-based music programs, such as trackers or software wavetables. This chunk is optional and no more than 1 may appear in a WAVE file.

Offset Size Description Value
0x00 4 Chunk ID "ltxt" (0x6C747874)
0x04 4 Chunk Data Size 7
0x08 1 Unshifted Note 0 - 127
0x09 1 Fine Tune (dB) -50 - +50
0x0A 1 Gain -64 - +64
0x0B 1 Low Note 0 - 127
0x0C 1 High Note 0 - 127
0x0D 1 Low Velocity 1 - 127
0x0E 1 High Velocity 1 - 127
Instrument Chunk Format

Unshifted Note
The unshifted note field has the same meaning as the sampler chunk's MIDI Unity Note which specifies the musical note at which the sample will be played at it's original sample rate (the sample rate specified in the format chunk).

Fine Tune
The fine tune value specifies how much the sample's pitch should be altered when the sound is played back in cents (1/100 of a semitone). A negative value means that the pitch should be played lower and a positive value means that it should be played at a higher pitch.

Gain
The gain value specifies the number of decibels to adjust the output when it is played. A value of 0dB means no change, 6dB means double the amplitude of each sample and -6dB means to halve the amplitude of each sample. Every additional +/-6dB will double or halve the amplitude again.

Low Note and High Note
The note fields specify the MIDI note range for which the waveform should be played when receiving MIDI note events (from software or triggered by a MIDI controller). This range does not need to include the Unshifted Note value.

Low Velocity and High Velocity
The velocity fields specify the range of MIDI velocities that should cause the waveform to be played. 1 being the lightest amount and 127 being the hardest.

Format Variations

The down side to the Wave file format's popularity is that out of the hundreds of programs that support it, many abuse or misuse it due to bad programming and/or poor documentation. Once some of these "naughty" programs get fairly popular and churn out millions of incorrect Wave files, the rest of the software industry is forced to deal with it and write code that can read the incorrect files. New code should never write these errors, but possibly read them. Below are a few exceptions that have been made to the strict/original Wave file format.
  • Incorrect Block Alignment value - this can be dealt with by calculating the Block Alignment with the formula mentioned above.
  • Incorrect Average Samples Per Second value - this can be dealt with by calculating the Average Samples Per Second with the formula mentioned above.
  • Missing word alignment padding - this can be difficult to deal with, but can be done by giving the user a warning when unrecognized chunk ID's are encountered where a one byte read offset produces a recognized chunk ID. This is not a concrete solution, but will usually work even if the program doesn't have a comprehensive list of legal IDs.