HanjaDS

From KBase

Jump to: navigation, search

Main_Page > NDS_Homebrew_Tutorial / 방명록


Contents

[edit] Introduction

딸래미가 게임만 하지 않고 공부도 할 수 있도록, 그리고 영어 못지 않게 한자를 아는 것도 중요한 것 같아서 만든 프로그램입니다. HanjaDS v03#Introduction 의 설명처럼, 태극천자문의 글자들을 준비했었지만 좀 더 일반적인 사용을 위해 v0.4 버전부터 [한국어문학회] 에서 다운받은 급수별 한자들을 넣었습니다. v0.6 에는 8급부터 1급까지 약 3500 자의 한자가 들어 있습니다. 폰트 파일 크기 문제로 3급 버전과 1급 버전을 나누어 배포합니다. v0.6 은 KanaDS v0.5 의 화면 구성에 기초하여 약간 변형하였습니다.

  • 사용된 한자 총 750자
    • 8급 한자 50자
    • 7급 한자 100자
    • 6급 한자 150자
    • 5급 한자 200자
    • 4급 한자 250자
    • 3급 한자 749자
    • 2급 한자 854자
    • 1급 한자 1123자

50의 배수로 딱 떨어지지 않는 이유는 아직 알지 못합니다. 아마도 글자가 빠졌을 것으로 생각됩니다. 방명록에 제보 바랍니다.

Font 는 Anti-aliasing 기법이 적용된 것을 사용합니다. 이에 대한 설명은 NDS Homebrew Application Framework#Font 에서 자세히 할 예정입니다 : p

[edit] License

누구나 자유롭게 소스를 가져다 쓸 수 있습니다. 다만 원작자를 표시해 주는 센스~

[edit] Version Number

현재 버전은 v0.6 입니다 (2008년 12월 26일자)

[edit] Download

#Screen_Shots_.26_Downloads 에서 소스 및 .nds 다운로드

[edit] Old Versions

[edit] Game Play

  • 활용방법
    • 글자 보기 화면에서는 위 화면에 글자가 표시되고 약 4초가 지나면 뜻과 음이 나타난다. 나타나기 전에 뜻과 음을 먼저 말하면 되며 ^_^ 모르는 글자는 기다렸다가 확인하고 다음 글자로 넘어간다
    • 승원이는 화살표 눌러가면서 모르는 글자가 몇 개인지 세는 방식으로 게임을 즐긴다.
  • 8급 한자부터 4급 한자까지 급수별로 정리가 되어 있다. 각 급수는 한자의 KSC5601 code 순서대로 정렬되어 있으며, Random 을 지원한다.

[edit] Used Library

GyonG's NDS Homebrew Application Framework 를 사용한다

[edit] Scene Description

[edit] InitScene

Image:HanjaDSv04_1.png

현재 메뉴는 다음과 같이 되어 있다

  • 천자문 글자 보기 (A)
  • 섞기/풀기 (X)
    • 예전 버전의 잔재. 고칠 예정임
  • About (B)

[edit] ViewScene

Image:HanjaDSv06_2.png

  • Key 조작
    • (<) 이전 글자
    • (>) 다음 글자
    • (^) 이전 10 글자
    • (v) 다음 10 글자
    • (L) 이전 급수
    • (R) 다음 급수
    • (Y) 랜덤 시작 급수 설정/해제
    • (X) 랜덤 끝 급수 설정/해제
    • (B) 도움말
    • (A) 힌트 끄기/보기
    • (start) 초기화면으로 돌아가기
  • 화면 구성
    • [위 화면]
      • 글자 - 공부하고자 하는 글자
      • 급수 - 급수와 50자씩의 세트 수
      • 순서 - 세트의 글자 수와 번호
      • 다음 - 다음에 나올 글자
    • [아래 화면]
      • 설명 - 글자의 훈과 음
      • 랜덤 - 랜덤의 시작/끝 글자
      • 도움 - 간단한 도움말

[edit] AboutScene

Image:HanjaDSv06_3.png

현재 버전 정보가 나온다. #InitScene 이나 #ViewScene 어느 곳에서 오더라도 아래 화면이 어두워지며 정보가 나타나며 아무 키나 누르면 이전 화면으로 되돌아간다.

v0.41 부터는 위/아래 화살표 키로 화면을 스크롤할 수 있다

[edit] Font Set

HanjaDS v0.6 에서 사용하는 FontSet 은 다음과 같다.

   FontSetEntry g_aFontSet[] = 
   {
       { FONTINDEX_DEF_ENGLISH,      FONTINDEX_NOTHING, LucidaConsole_10pt_8x13_gfn },
       { FONTINDEX_DEF_KOREAN,       FONTINDEX_DEF_ENGLISH,  malgun_10pt_12x13_gfn },
       { FONTINDEX_DEF_HANJA,        FONTINDEX_DEF_KOREAN,   haeseo_all_24pt_30x32_gfn },
       { FONTINDEX_BIG_HANJA,        FONTINDEX_DEF_HANJA, haeseo_120pt_160x160_gfn },
       { FONTINDEX_TITLE_HANJA,      FONTINDEX_NOTHING, haeseo_68pt_84x92_gfn },
       { FONTINDEX_SMALLEST_ENGLISH, FONTINDEX_NOTHING, LucidaConsole_5pt_5x7_gfn },
       { FONTINDEX_NOTHING,          FONTINDEX_NOTHING, NULL }
   };

위 정보는 다음과 같이 해석된다.

  • 기본으로 사용하는 한글은 맑은고딕 10pt (12x13), 영어는 Lucida Console 10pt (8x13) 이다
  • 작은 한자는 한양해서 24pt (30x32) 이다.
  • 큰 한자는 한양해서 120pt (160x160) 이다.
  • #InitScene 의 "천자문" 부분은 한양해서 68pt (84x92) 를 사용하였다. "천", "자", "문" 세 글자만 들어 있다.
  • Debug 용 font 로 Lucida Console 5pt (5x7) 를 사용한다.

각 폰트 파일의 크기는 다음과 같다.

2.8K LucidaConsole_10pt_8x13.gfn
1.6K LucidaConsole_5pt_5x7.gfn
2.2M haeseo_120pt_160x160.gfn
1.7K haeseo_68pt_84x92.gfn
809K haeseo_all_24pt_30x32.gfn
139K malgun_10pt_12x13.gfn

폰트 데이터 크기 문제로 3급 버전과 1급 버전으로 분리하였다. 1급 버전을 빌드할 때는 아래 파일을 haeseo_120pt_160x160.gfn 대신 넣고 파일 이름을 haeseo_120pt_160x160.gfn 로 고쳐서 다시 빌드하였다.

2.4M haeseo_2-1_96pt_128x128.gfn

1급 버전의 경우 3급 버전보다 글씨가 조금 작다. 3급 버전의 것과 같은 크기를 쓰면 다음 파일이 만들어지는데

3.0M haeseo_2-1_120pt_160x160.gfn

위의 파일을 사용하면 크기가 4M 가 넘어가 버리므로 빌드가 되지 않는다.

[edit] Hanja Data

[edit] HanjaChar

글자 하나에 대한 정보를 기록한다. 뜻과 음은 2개 이상이 될 수도 있다고 가정했지만 현재 하나만 사용하고 있다. HanjaDS v03 에서는 여러 개의 음훈에 대해 배열을 사용했지만 v0.4 에서는 Null-character 로 분리된 하나의 String 으로 저장하고 있다.

 struct HanjaChar {
   int keup;
   const char *ch;
   const char *data;
 };

각 글자에 대한 실제 데이터는 다음과 같이 기록하며, KSC5601 code 순서로 정렬되어 있다.

 static HanjaChar g_chars[] = {
   { 8, "敎", "가르칠 교\0" },
   { 8, "校", "학교 교\0" },
   { 8, "九", "아홉 구\0" },
   { 8, "國", "나라 국\0" },
   { 8, "軍", "군사 군\0" },
 
   (중략)
 
   { 4, "回", "돌아올 회\0" },
   { 4, "吸", "숨들이쉴 흡\0마실 흡\0" },
   { 4, "興", "일 흥\0" },
   { 4, "希", "바랄 희\0" },
 
   { 3, "佳", "아름다울 가\0" },
   { 3, "暇", "틈 가\0겨를 가\0" },
   { 3, "架", "시렁 가\0" },
   { 3, "刻", "새길 각\0" },
 
   (중략)
 
   { 1, "洽", "흡족할 흡\0" },
   { 1, "犧", "희생 희\0술그릇 사\0" },
   { 1, "詰", "물을 힐\0꾸짖을 힐\0" },
 };

[edit] Retrieving Hanja Data

수천 자에 달하는 한자 데이터를 일일이 타이핑해 넣었을 리 만무다. 약간의 노가다는 있었지만, 웬만한 것은 간단한 프로그램을 짜서 얻었다.

Media:retrieve_hanja_data.zip 에 필요한 파일들을 올려 두었다.

[edit] 급수별 한자 얻기

[한국어문학회] 자료실에 가면 각 급수별 한자들이 정리되어 올라와 있다. HWP 로 되어 있어서 [Naver 자료실] 로부터 HWP Viewer 를 다운로드 받았다. 여기서 한자를 추출하여 급수별 한자 문자열을 만든다.

이때 주의할 것은 Code Page 인데, 어떤 글자들은 KSC5601 의 4880 한자에 포함되지 않은 것도 있다. 예를 들어 "굳셀 강" 으로 읽히는 强 자의 경우 KSC5601 에는 오른쪽 윗부분이 "입 구" (口) 로 되어 있지만, 한국어문학회의 자료에는 세모 모양의 "마늘 모" (去 자의 아래 부분) 로 되어 있다. 이 글자는 일본어 Code Page 에 있는 글자인데, 이런 식의 글자들이 몇 개 있다. Notepad 에 붙여 넣었을 때 ? 로 나오는 글자들이 무슨 글자인지 잘 찾아서 붙여 넣어 주면 된다.

위 자료에는 7급에 8급 한자가, 6급에 7급 한자가 포함되어 있으므로 각 급수 한자만 추출하기 위하여 간단한 PERL 프로그램을 만들어 돌렸다.

list_hanja.pl

 (data 부분은 생략)
 
 for $k (1 .. 8) {
       $str = $strs{$k};
       next unless defined ($str);
       $end = length($str) / 2 - 1;
       for $i (0 .. $end) {
               $ch = substr($str, 2*$i, 2);
               $da = $chars{$ch};
               $ch2{$ch} = [ $k, $da ];
               # $n = sprintf("%3d", $i+1);
               # print "$n $ch $k $da\n";
       }
 }
 
 for $ch (keys %ch2) {
       $r = $ch2{$ch};
       ($k, $da) = @$r;
       $r3 = $ch3{$k};
       unless ($r3) {
               my @arr;
               $r3 = \@arr;
       }
       push(@$r3, [ $ch, $k, $da ]);
       $ch3{$k} = $r3;
 }
 
 for $k (1 .. 8) {
       $r3 = $ch3{$k};
       for $r (@$r3) {
               ($ch, undef, $da) = @$r;
               print "$k $ch $da\n";
               # print "$ch";
       }
 }

한자를 추출하는 역할 뿐 아니라, 기존 C++ 소스에 있던 음/훈이 있는 경우 그대로 가져 오는 역할까지 하고 있다. 이 프로그램을 돌린 결과는 다음과 같다.

hjdata.txt

(앞부분 생략)
8 月 달 월
8 白
8 土 흙 토
8 日 해 일
8 北
8 女 여자 녀
8 學

음/훈 이 있는 것은 v0.3 에서 가져 온 글자들이다. v0.3 까지만 해도 직접 입력했었기 때문에, 아까워서 가급적 직접 입력한 것으로 사용하려고 했다.

[edit] 음훈 얻기

네이버 한자사전에서 여덟 팔(八) 자를 검색해 보면 주소 부분은 다음과 같이 변한다

 http://hanja.naver.com/search.nhn?query_euckr=&dic_where=hanja&query=%F8%A2

결과에서 검색범위를 전체로 하지 않고 "음,한자" 로 하면 URL 은 좀 더 단순해진다. URL 뿐 아니라 결과 화면도 단순하다.

 http://hanja.naver.com/search.naver?where=srch_keyword&query=%F8%A2

[wget] 을 사용하여 위 page 를 받아서

 wget -O '8.html' 'http://hanja.naver.com/search.naver?where=srch_keyword&query=%F8%A2'

"여덟 팔" 을 검색해 보면 다음과 같은 라인이 있다는 것을 알게 된다.

 <tr><td align=left     (중략)     class="bl-uu01 p3">여덟 팔</a>

bl-uu01 p3 이라는 class 는 이 page 에 다시 나오지 않는다. 따라서 이것을 잘 이용해 보면 어떤 글자든지 음과 훈을 얻어낼 수 있다는 말이 된다. 약 1급까지 3천자가 넘는 글자를 다 받으려니 시간은 꽤 걸렸지만, 잠시 딴 짓을 했다.

query.pl

 #!/usr/bin/perl
 
 $prefix = 'http://hanja.naver.com/search.naver?where=srch_keyword&query=';
 
 open(TXT, "all.txt") or die;
 $chars = <TXT>; chomp $chars;
 close(TXT);
 
 $end = length($chars) / 2 - 1;
 
 for $i (0 .. $end) {
       $ch  = substr($chars, 2*$i, 2);
       $ch1 = substr($chars, 2*$i, 1);
       $ch2 = substr($chars, 2*$i+1, 1);
       $as1 = ord($ch1);
       $as2 = ord($ch2);
       $encoded = sprintf("%%%02X%%%02X", $as1, $as2);
       $url = $prefix.$encoded;
       # print "$url\n";
       $cmd = "wget -O - '$url' | grep -Poh 'bl-uu01.+</a>'";
       $result = `$cmd`;
       # print " Result: $result\n";
       $result =~ s/.+>(.+)<.+$/\1/;
       $result =~ s/\s*$//;
       # print " Result: $result\n";
       print "$ch $result\n";
 }

all.txt 는 필요한 모든 한자를 다 넣어 둔 파일이다. 위의 query.pl 을 실행하여 meaning.txt 로 저장했다.

[edit] C++ Source Generation

위와 같이 얻은 정보들을 정리하여 C++ Source 로 만들어낸다. hjdata.txt 와 meaning.txt 를 이용하여 C++ 을 만든다.

addm.pl

 #!/usr/bin/perl
 
 open(HJ, "hjdata.txt") or die $!;
 while (<HJ>) {
       ($k, $ch,$da) = /(\d)\s(\S+)\s(.*?)\s*$/;
       push(@all, [$k, $ch, $da]);
 }
 close(HJ);
 
 open(MN, "meaning.txt") or die $!;
 while (<MN>) {
       ($ch, $da) = /^(\S+)\s(.*?)\s*$/;
       $da =~ s/\(.+?\)//g;
       my @data = split(/[,\/]\s?/, $da);
       $meaning{$ch} = \@data;
 }
 close(MN);
 
 @sorted = sort {
       $c1 = $a->[0] <=> $b->[0];
       return -$c1 if ($c1 != 0);
       return $a->[1] cmp $b->[1];
 } @all;
 
 for $r (@sorted) {
       ($k, $ch, $da) = @$r;
       $rda = $meaning{$ch};
       $nda = @$rda;
       if ($da ne  and $da ne $rda->[0]) {
               unshift(@$rda, $da);
       }
 
       $data = join('\0', @$rda);
       print <<EOM;
 { $k, "$ch", "$data\\0" },
 EOM
 }

위 소스의 블럭들은 각각 hjdata.txt 읽기, meaning.txt 읽기, sort 하기, 출력하기 의 역할을 수행한다. sort 는 급수로 먼저 정렬하여 8급이 7급보다 먼저 나오게 하고, 그 다음 ascii code 로 정렬 (결과적으로 KSC5601 순서가 된다) 했다.

네이버에서 받아 온 음과 훈이 내가 직접 타이핑한 것과 같으면 그대로 살리고, 직접 타이핑한 것이 없으면 네이버의 것으로 대체했다. Null-Character (\0) 로 구분하도록 하였다.

이렇게 나온 결과는 result.cpp 에 저장하여 적당히 편집한 후 HanjaData.cpp 로 옮겼다. 물론, 3급부터 1급까지는 comment out 했다.

[edit] Screen Shots & Downloads

[edit] hanjaDS

2009.03.25
v0.61 (4급 버전을 올립니다. DSTT 에서 실행되지 않는 것이 혹시 파일크기 문제인가 해서 4급까지만 큰글자로 나오는 버전을 급히 만들어 보았습니다. A 버튼 버그도 수정하였습니다)
Media:HanjaDS_4keup.nds.090325.zip - 8급~4급 HanjaDS.nds 만
2008.12.26
v0.6 (3급버전과 1급버전은 글자 크기만 다를 뿐 한자는 모두 들어 있습니다)
Media:HanjaDS_3keup.nds.081226.zip - 8급~3급 HanjaDS.nds 만
Media:HanjaDS_1keup.nds.081226.zip - 2급~1급 HanjaDS.nds 만
Media:HanjaDS.081226.zip - 모든 소스

Image:HanjaDSv06_3.png

2008.07.25
v0.41
Media:HanjaDS.nds.080725.zip - HanjaDS.nds 만
Media:HanjaDS.080725.zip - 모든 소스

Image:HanjaDSv041_3.png

2008.07.20
v0.4
Media:HanjaDS.nds.080720.zip - HanjaDS.nds 만
Media:HanjaDS.080720.zip - 모든 소스

Image:HanjaDSv04_1.png - Image:HanjaDSv04_2.png - Image:HanjaDSv04_3.png

[edit] Links

[edit] Other stuffs

NDS Homebrew Tutorial 
Homebrew 와 관련된 정보들을 모아 놓은 홈
Biological Warfare DS 
세균전 for NDS

[edit] Guestbook

GyonG 방명록 에 글도 써 주삼~ 요청합니다!

Personal tools
Wiki Help (mediawiki.org)