01 NDS 롬(ROM) 파일 포맷(Format) 분석
원문 : http://kkamagui.springnote.com/pages/417484
들어가기 전에...
- 이 글은 kkamagui에 의해 작성된 글입니다.
- 마음껏 인용하시거나 사용하셔도 됩니다. 단 출처(http://kkamagui.tistory.com, http://kkamagui.springnote.com)는 밝혀 주십시오.
- 기타 사항은 mint64os at gmail.com 이나 http://kkamagui.tistory.com으로 보내주시면 반영하겠습니다.
- OS 제작에 대한 상세한 내용은 책 "64비트 멀티코어 OS 구조와 원리"를 참고하기 바랍니다.
0. 시작하면서...
devkitARM이 *.nds 파일을 만드는 과정을 살펴보면 makefile을 참조해서 살펴보면 아래와 같은 과정을 거친다.
- object 파일을 링크하여 *.elf 파일을 만든다.
- *.elf 파일을 objcopy -O binary 옵션을 이용하여 코드와 데이터 영역만 추려내서 순수한 바이너리 파일인 *.arm9 or *.arm7 파일을 만든다.
- ndstool을 사용해서 *.arm9파일을 *.nds 파일로 만든다.
그럼 도대체 이 NDS Rom 파일은 어떤 구조로 되어있는 것일까? 자세히 살펴보자.
1. NDS 롬(ROM) 헤더(Header) 구조
http://www.bottledlight.com/ds/index.php/FileFormats/NDSFormat를 참조하면 실제 어떤 구조로 되어있는지 알 수 있다.
Header format
Field Start End Size Example data (Metroid demo) Game title 0x000
0x00B
12
"FIRST HUNT "
Game code 0x00C
0x00F
4
"AMFE"
Maker code 0x010
0x011
2
"01"
(Nintendo)Unit code 0x012
0x012
1
0x00
Device code 0x013
0x013
1
0x00
Card size 0x014
0x014
1
0x07
(2^(20 + 7) = 128Mb = 16 MB)Card info 0x015
0x01E
10
0x00's
Flags 0x01F
0x01F
1
0x00
ARM9 source (ROM) 0x020
0x023
4
0x00004000
(must be 4 KB aligned)ARM9 execute addr 0x024
0x027
4
0x02004800
ARM9 copy to addr 0x028
0x02B
4
0x02004000
ARM9 binary size 0x02C
0x02F
4
0x00081D58
ARM7 source (ROM) 0x030
0x033
4
0x000B3000
ARM7 execute addr 0x034
0x037
4
0x02380000
ARM7 copy to addr 0x038
0x03B
4
0x02380000
ARM7 binary size 0x03C
0x03F
4
0x00026494
Filename table offset (ROM) 0x040
0x043
4
0x000D9600
Filename table size 0x044
0x047
4
0x11B6
FAT offset (ROM) 0x048
0x04B
4
0x000DA800
FAT size 0x04C
0x04F
4
0x678
ARM9 overlay src (ROM) 0x050
0x053
4
0x00085E00
ARM9 overlay size 0x054
0x057
4
0x60
ARM7 overlay src (ROM) 0x058
0x05B
4
0
ARM7 overlay size 0x05C
0x05F
4
0
Control register flags for read 0x060
0x063
4
0x00586000
Control register flags for init 0x064
0x067
4
0x001808F8
Icon+titles (ROM) 0x068
0x06B
4
0x000DB000
Secure CRC16 0x06C
0x06D
2
0xC44D
ROM timeout 0x06E
0x06F
2
0x051E
ARM9 unk addr 0x070
0x073
4
0x020049EC
ARM7 unk addr 0x074
0x077
4
0x02380110
Magic number for unencrypted mode 0x078
0x07F
8
0x00's
ROM size 0x080
0x083
4
0x00EE3E44
Header size 0x084
0x087
4
0x4000
Unknown 5 0x088
0x0BF
56
0x00's
GBA logo 0x0C0
0x15B
156
data
Logo CRC16 0x15C
0x15D
2
0xCF56
Header CRC16 0x15E
0x15F
2
0x00F8
Reserved 0x160
0x1FF
160
0x00's
The control register flags contain latency settings and depends on the ROM manufacturer (Macronix, Matrix Memory).
Unknown2a and 'Header Size' contain flags that are (somewhat) used during boot as part of card CR writes. Unknown2b contains the size of a certain type of transfer done during boot, but it's range checked and cannot be reduced. Unknown3c is seemingly unused, and some code paths get data from 0x160 onward (only 0x170 bytes of a header fetch are actually retained by the BIOS)
Secure CRC16 calculation is performed on the ROM from 0x4000 to 0x7FFF, with an initial value of 0xFFFF.
Logo CRC16 calculation is performed on the header from 0x0C0 to 0x15B, with an initial value of 0xFFFF.
Header CRC16 calculation is performed on the header (after the previous two CRCs are filled) from 0x000 to 0x15D with an initial value of 0xFFFF.
Device code needs lower 3 bits to be 0. This is a similar behavior as GBA header.
위의 정보를 보면 롬 영역 안쪽에 FAT File System이 들어가는 것을 알 수 있다. 즉 게임에서 필요한 데이터를 내부에 플래쉬에 저장하여 읽고 쓴다는 이야기다. @0@)/~ 참으로 놀라운 사실이 아닐 수 없다.
저 부분을 분석하면 게임 내부에서 사용하는 데이터도 추출해 낼 수 있다는 말이된다. 물론 좀더 분석해봐야 알겠지만 상당히 흥미로운 사실이다.
1.1 ARM9 ROM의 시작 위치
위에서 Header Size를 보면 0x4000으로 설정되어있다. ARM9 ROM의 시작위치는? 0x4000 인걸 알 수 있다. 옆에 "4Kbyte로 반드시 정렬해라"라는 이야기가 있는데, 게임롬에만 해당하는 건지 확실히 알 수 없지만 굳이 하지 않아도 될 것 같다. 특히 홈브루 같은 경우는 더욱...
위 결과로 미루어 보면 ROM Header의 바로 뒤에 ARM9의 코드가 들어감을 알 수 있다.
1.2 ARM7 ROM의 시작 위치
ARM7의 코드가 포함된 ROM의 위치는 ARM9의 바로 뒤에 연결 되어있지 않다. 다만 0x1000의 배수(4Kbyte)에 맞추어서 시작하고 있다.
ARM7 코드가 로딩되는 위치의 주소를 보면 0x2380000으로 4Mybte의 메인 메모리 뒷쪽에 자리잡고 있다. NDS 게임의 경우 ARM7이 하는 일이 그렇게 많지 않아 뒷쪽으로 할당한 것 처럼 보인다.
1.3 롬 실행 시 메모리 배치
롬 헤더에 보면 롬파일 내에 ARM9/7 코드가 어디서 시작하고 크기는 얼마나 되며 메모리에 어느 위치에 복사해주는지 정보가 나와있다. 또한 Entry 정보도 나와있는 걸로 보아 시작 시에 해당 메모리 위치로 코드를 복사하고 시작함을 알 수 있다.
2.아이콘(Icon) 및 광고(Banner) 헤더(Header) 구조
Icon + logo format (the banner)
This is a structure of size 32+512+32+256*6 = 2112 bytes with the following format:
Banner structure
Offset Size Description 0 2 Version (always 1) 2 2 CRC-16 of structure, not including first 32 bytes 4 28 Reserved 32 512 Tile Data 544 32 Palette 576 256 Japanese Title 832 256 English Title 1088 256 French Title 1344 256 German Title 1600 256 Italian Title 1856 256 Spanish Title
The icon is a 32x32 picture formed out of 4x4 16 color tiles and a single 16 color palette.
Following the icon data (icon offset + 576 bytes), are 6 unicode game titles, displayed in the DS menu depending on the selected language mode. Each title is padded to 128 characters (256 bytes).
The strings are in the same order as the language choice in Firmware.
게임 아이콘 및 설명을 넣는 부분 같다. 아이콘이나 게임 타이틀 부분도 ndstool.exe를 이용하면 쉽게 넣을 수 있으므로 나중에 참고하자.
3.실제 롬 파일 분석
3.1 헤더 분석
devkitPro를 설치하면 자동으로 설치되는 ndstool.exe 프로그램을 이용해서 KKAMAGUI NOTEPAD 롬파일을 분석해 보자. KKAMAGUI NOTEPAD의 롬파일은 00 KKAMAGUI NOTEPAD 에서 구할 수 있다. dstool.exe 프로그램은 아래와 같은 다양한 옵션을 가지고 있다.
위의 옵션 중에 -i 옵션을 이용하면 롬의 정보를 볼 수 있다. i 옵션을 이용하여 롬 파일을 분석해 보자.
-
D:\devkitPro\MyProject\NotePad>ndstool -i NotePad.nds
Nintendo DS rom tool 1.33 - Jan 28 2007 21:02:20
by Rafael Vuijk, Dave Murphy, Alexei Karpenko
Header information:
0x00 Game title .
0x0C Game code ####
0x10 Maker code
0x12 Unit code 0x00
0x13 Device type 0x00
0x14 Device capacity 0x01 (2 Mbit)
0x15 reserved 1 000000000000000000
0x1E ROM version 0x00
0x1F reserved 2 0x04
0x20 ARM9 ROM offset 0x200
0x24 ARM9 entry address 0x2000000
0x28 ARM9 RAM address 0x2000000
0x2C ARM9 code size 0x31794
0x30 ARM7 ROM offset 0x31A00
0x34 ARM7 entry address 0x37F8000
0x38 ARM7 RAM address 0x37F8000
0x3C ARM7 code size 0x12B8
0x40 File name table offset 0x32E00
0x44 File name table size 0x9
0x48 FAT offset 0x33000
0x4C FAT size 0x0
0x50 ARM9 overlay offset 0x0
0x54 ARM9 overlay size 0x0
0x58 ARM7 overlay offset 0x0
0x5C ARM7 overlay size 0x0
0x60 ROM control info 1 0x007F7FFF
0x64 ROM control info 2 0x203F1FFF
0x68 Icon/title offset 0x0
0x6C Secure area CRC 0x0000 (-, homebrew)
0x6E ROM control info 3 0x051E
0x70 ARM9 ? 0x0
0x74 ARM7 ? 0x0
0x78 Magic 1 0x00000000
0x7C Magic 2 0x00000000
0x80 Application end offset 0x00033000
0x84 ROM header size 0x00000200
0xA0 ? 0x4D415253
0xA4 ? 0x3131565F
0xA8 ? 0x00000030
0xAC ? 0x53534150
0xB0 ? 0x00963130
0x15C Logo CRC 0x9E1A (OK)
0x15E Header CRC 0x32B1 (OK)
홈브루의 경우는 게임의 경우와 조금 달리 ARM7의 이미지가 0x1000에서 시작하지 않고 있음을 알 수 있다. 그리고 ARM7의 코드가 4Mbyte의 공유영역에 올라가있는 것이 아니라 0x37F8000 주소에 Private RAM(64Kbyte)에 위치하고 있다. 02 NDS Spec에 보면 메모리 맵에 대한 자세한 내용을 알 수 있다.
Secure area CRC 부분을 보면 이 값이 0x0000 이고 homebrew라고 표시되어있다. 실제 게임은 이 값이 0이 아닌 것일까? 몇가지 게임 롬을 분석해본 결과... 0x0000 이 아님을 알 수 있었다. 보안에 관련된 영역을 검사하는데 사용되는 것으로 생각된다.
3.2 FAT 영역 분석
롬 파일 내부에 FAT 영역을 가진다. ndstool.exe 를 이용하면 -l 옵션으로 FAT 영역의 데이터를 볼 수 있다. KKAMAGUI NOTEPAD의 경우 FAT 영역에 별다른 데이터를 가지지 않으므로 다른 홈브루나 게임 롬을 열어봐야 된다. 홈브루 중에서는 아마 찾기 힘들 것이므로 게임 롬을 열어보자. 디렉토리 구조와 파일들이 줄줄이 나오는 것을 알 수 있다.
<ndstool.exe를 이용해서 롬 파일의 FAT 영역을 분석한 화면>
그렇다면 ROM 파일에 있는 FAT 파일 시스템은 우리가 윈도우에서 포맷할 때 만들어지는 모든 파일 시스템 정보를 포함하고 있을까?
이 부분은 ROM 파일을 열어서 확인을 해봐야 할 것 같다.
여기 체우기...
4. 데이터 영역 분석
롬 데이터 영역은 .arm9 및 .arm7의 파일의 덤프 형태로 되어잇는데, 자세한 내용은 00 NDS makefile 및 NDS 파일 생성 과정 분석 페이지를 참조하자.
마치며...
이상으로 NDS 롬 파일 구조에 대해서 알아보았다. 특별히 암호화도 되어있지 않고 checksum을 이용해서 롬 파일의 유효성을 체크한다.
롬 파일의 구조를 알았으니, 그 안에서 데이터를 뽑아내어 언어를 한글화 한다던지, 그림 파일을 바꾼다던지 하는 것고 그리 어렵지 않을꺼라 생각한다.
다시 NDS의 세계로 빠져보자 @0@)/~~
이 글은 스프링노트에서 작성되었습니다.
'NDS 홈브루(Homebrew) > 홈브루 Tutorial' 카테고리의 다른 글
03 비디오 모드 제어(Video Mode Control) (0) | 2007.11.14 |
---|---|
02 NDS Hardware Spec And Memory Map (0) | 2007.11.14 |
01 libfat 업그레이드 (2) | 2007.11.14 |
00 NDS 홈브루 프로젝트 생성 (8) | 2007.11.14 |
00 NDS 개발 킷(Devkit Pro) 설치 (0) | 2007.11.14 |