봄버맨
우선 다음 2개의 프로그램을 준비해주세요.
Human68k System Disk 버전은 아무거나 상관없습니다3.02버전 사용
“DB.x” “C-Compiler PRO68K”에 들어있습니다2.11에 포함된 디버거 v3.0
그러면 해석용 디스크를 작성해봅시다. 우선, 드라이브 0에 시스템 디스크를 넣고 X68000의 전원을 넣습니다. 그러면 비쥬얼 셸이 기동했지요?Human68k v2.0x의 경우, 3.0x대면 바로 DOS화면이 뜬다 전차 그림이 그려져있는 사각의 상자가 있지 않나요? 마우스를 조작해 화살표를 그 전차 의 바로 위에 가져가 주세요. 그리고 마우스의 왼쪽 버튼을 2회 빠르게 눌러주세요. 그러면 화면이 어두워지고 “A>”라는 문자가 나왔나요? 그러면 드라이브 1에 공디스크(지워도 상관없는 디스크)를 넣어주세요.


그리고, “A>Format B: /S”라고 입력한 다음 리턴 키를 눌러주세요. 포맷이 끝나고 시스템 전송이 끝나면 “Command.x”를 전송합니다. 만약 게임 디스크를 복사해 백업본을 만드는 과정이라면 2.0x버전 대 Human68k를 우선 사용할 것. 안 그러면 버전 차이로 실행 안 될 수도 있다.
A>COPY A:¥Command.x B:¥
라는 느낌입니다. 다음에 “DB.x”가 들어있는 디스크와 시스템 디스크를 바꿔 넣습니다.
그리고,
COPY DB.x B:¥
를 실행해 “DB.x”를 전송합니다. 이것으로 해석용의 디스크가 완성되었습니다. 양 드라이브의 디스크를 꺼내고, 해석용 디스크를 드라이브 0에 넣은 뒤 리셋을 눌러 주세요. 그러면
Human68k for X68000 version 3.02
Copyright 1987,88,89,90,91,92,93 SHARP/Hudson
Command version 3.00
A>
라고 표시되었지요? 표시 되지 않았다면, 다시 한 번 작업해 주세요. 그러면 “봄버맨”을 해석해 봅시다. 드라이브 1에 봄버맨의 디스크를 넣고 “DB.x”를 기동합시다. “DB”라고 누르고 리턴키를 눌러 주세요.
A>DB
X68k Debugger v3.00 Copyright 1987-1993 SHARP/Hudson
Micro Processor Unit:16bit MC68000
Floating Point Co Processor:Softwere emulation.
-
여기까지 끝냈다면 준비는 끝입니다. 그러면 항상 사용하고 있는 플로피 디스크의 간단한 설명을 합니다.
여러분은 CD를 가지고 있나요? CD는 곡목마다 번호가 나뉘어져있습니다. 그것을 트랙이라고 부릅니다. 그리고 트랙 속에도 이런저런 파트로 나뉘어 있고 그것을 인덱스라고 부릅니다.

그것과 마찬가지로 플로피 디스크에도 트랙과 인덱스와 같은 것이 있습니다. 표준으로 X68000상에서 사용할 수 있는 디스크의 초기 구조를 설명하자면, 트랙위 이미지의 오렌지색 원 (플로피 디스크의 경우는 실린더라 부릅니다)이 77개. 거기에 그 한 트랙을 8개로 나누고 있습니다. 덧붙여 말하자면 플로피 디스크에서는 인덱스라고 부르지 않고 섹터위 이미지의 파란색 부분라 부릅니다. 그리고, 플로피 디스크의 뒷면을 사용할 수 있습니다. (앞뒤를 구별하는 것을 헤드 또는 서피스라 부릅니다. 앞면이 0이고 뒷면이 1입니다. 보통은 0실린더인 앞면을 0트랙, 0실린더인 뒷면을 1트랙이라 부릅니다. 1실린더인 앞면은 2트랙, 1실린더인 뒷면은 3트랙이라는 식입니다)그러므로, 결국, 154 트랙 사용이 가능합니다. 1섹터의 사이즈는 $400바이트 고정이므로(어디까지나 Human68K 표준 디스크입니다),
$400섹터 사이즈 × 8트랙당 섹터 수 × 154트랙 수 = 1261568바이트 = 1232K바이트
다시말해, 1.2M바이트 사용할 수 있습니다. 예로 0 ~ 2트랙의 상태를 표시해 써봅니다.
0트랙의 상태 1트랙의 상태 2트랙의 상태 3트랙의 상태
↓ ↓ ↓ ↓
C H R N C H R N C H R N C H R N
00 00 01 03 00 01 01 03 01 00 01 03 01 01 01 03
00 00 02 03 00 01 02 03 01 00 02 03 01 01 02 03
00 00 03 03 00 01 03 03 01 00 03 03 01 01 03 03
00 00 04 03 00 01 04 03 01 00 04 03 01 01 04 03
00 00 05 03 00 01 05 03 01 00 05 03 01 01 05 03
00 00 06 03 00 01 06 03 01 00 06 03 01 01 06 03
00 00 07 03 00 01 07 03 01 00 07 03 01 01 07 03
00 00 08 03 00 01 08 03 01 00 08 03 01 01 08 03
* 0트랙은 0실린더C00의 앞면H00. 2트랙은 1실린더C01의 앞면H00.
* 1트랙은 0실린더C00의 뒷면H01. 3트랙은 1실린더C01의 뒷면H01.
C = 실린더
H = 헤드 또는 서피스 0이라면 앞면 1이라면 뒷면
R = 레코드 섹터의 배열을 표시합니다트랙마다 8개씩
N = 섹터 길이 1섹터의 크기를 나타냅니다
섹터 길이의 번호 내역
0 = $0080
1 = $0080 × 2 = $0100 Byte
2 = $0100 × 2 = $0200 Byte
3 = $0200 × 2 = $0400 Byte
4 = $0400 × 2 = $0800 Byte
5 = $0800 × 2 = $1000 Byte
6 = $1000 × 2 = $2000 Byte
다시말해, Human68k의 표준 디스크는 섹터 길이 3이므로, 1섹터의 사이즈가 $400 바이트가 되는 것입니다. 위와 같은 틀을 ID라 부릅니다만, 디스크의 포맷이라고 하는 것은 위에 써놓은 것과 같은 어떤 일정한 규정의 틀을 작성해 플로피 디스크를 사용할 수 있도록 하기 위한 작업입니다. 컴퓨터에서는 어떤 식으로 디스크를 읽고 쓰는가 하면 “30트랙의 2섹터째를 읽어 들여라”라거나 “152트랙의 8섹터째에 써 넣어라”라는 식으로 합니다.
예를들면, 121 트랙의 5섹터를 읽으려고 하면
C=$3C60실린더 H=$01뒷면 R=55번째 섹터 N=3 ($3C × 2 + 1 = 121)
이라는 식으로 컴퓨터는 지정하고 있습니다. 그러면 본제로 넘어갑시다. 디스크 프로텍트라는 것은 대체 어떤 원리로 되어있는 것일까요? 간단히 말하자면, 위에 적은 표준 포맷이라면 X68000상에서도 작성할 수 있지만, 일부러 일반적으로는 작성할 수 없는 비표준 포맷을 디스크 특정 부분에 만들어 두고, 그곳의 트랙을 읽었을 때 제대로 읽을 수 있는가(일반적으로 디스크 복사를 했다면 복사할 때 비표준 포맷을 작성할 수 없으므로 그 부분을 읽을 수 없음) 아닌가를 살피고, 읽어들일 수 있다면 게임 그외의 부분이 아무일 없이 실행되고, 읽을 수 없었다면 이상한 동작을 하도록 한다. 이런 느낌입니다. 어떤가요? 이해할 수 있나요? 지금부터 하려는 것은 이런 비표준 포맷을 강제로 재현해, 마스터 디스크와 같은 동작을 하도록 한다라는 것이 아니라 프로그램 속에 프로텍트 체크를 하고 있는 부분이 있으므로, 백업을 하더라도 거기를 백업 디스크라고 판단하지 않도록 만들고 마치 마스터 디스크와 같은 동작을 하도록 하는 방식으로 디스크의 백업을 한다 라는 작업입니다.
그러면 “봄버맨”의 해석을 해봅시다.
선행작업한 해석용 디스크를 드라이브 0, 봄버맨을 디스크 1에 넣고, X68000의 전원을 넣어주세요. “A>”가 나왔습니까? 그러면 봄버맨의 디스크에 무엇이 들어있는지 살펴봅시다. 파일의 내용물을 보는 커맨드는 “DIR”입니다. 그러면 B드라이브의 내용을 살펴봅시다.
A>DIR B:
ボリュームがありません B:¥
8ファイル 679K Byte 使用中 542K Byte 使用可能
ファイル使用量 618K Byte 使用
COMMAND X 28026 90-05-05 12:00:00
CONFIG SYS 45 91-03-01 18:06:08
AUTOEXEC BAT 33 91-03-01 18:16:54
OPMDRV X 26392 90-05-15 12:00:00
FLOAT2 X 12844 90-05-05 12:00:00
EYEC X 15050 91-04-04 10:12:56
OPDRV X 5554 91-02-13 16:16:06
BM X 539714 91-04-03
이것이 봄버맨의 디스크 내용물입니다.
Human68k는 기동시에 이런저런 프로그램을 자동적으로 등록하는 것이 가능합니다.
그 등록하는 내용이 들어있는 파일이 “Config.sys”입니다. 그 내용물을 보면 봄버맨을 기동할 때에 시스템에 무엇이 등록되는지 알 수 있습니다. 파일의 내용을 보는 커맨드는 “TYPE”입니다. 그러면 “Config.sys”의 내용물을 살펴봅시다.
A>TYPE B:Config.sys
DEVICE = OPMDRV.X FM음원의 연주를 간이로 행하는 프로그램입니다.
DEVICE = FLOAT2.X 부동소수점 연산을 간이로 행하는 프로그램입니다.
그러면, 그 다음에 Human68k는 “AutoExec.Bat”이라는 파일 속에 등록되어있는 파일을 자동적으로 등록합니다. 그러면 그 내용물을 살펴봅시다.
A>TYPE B:AutoExec.Bat
ECHO OFF 배치파일의 동향을 표시하지 않도록 합니다.
eyec 아마도 오프닝 관련의 프로그램이라고 생각합니다.
opdrv >NUL 아마도 봄버맨용의 "OPMDRV.x"라고 생각합니다.
bm "봄버맨" 본체입니다.
사실은 “EYEC.x”도 “OPDRV.x”도 제대로 살펴보아야 하지만, 이 2개에는 프로텍트 체크는 없었으므로 생략합니다.
해석 작업에 들어가기 전에 우선 봄버맨 디스크를 백업 작업한다. 공디스크를 1드라이브에 넣고 FORMAT B: /S로 시스템을 옮겨준다. 이때 Human68k는 2.0x대를 이용한다. 만약 3.0x를 이용하면 Human68k 버전차이로 후에 모든 프로텍트 제거 작업이 완료되어도 게임이 실행되지 않고 에러를 내며 멈춘다. 포맷이 끝났으면 원본 디스크의 내용을 COPY *.* B: 로 모두 옮겨 준다. 이 백업된 디스크를 다시 0드라이브에 넣고 리셋해주면 제작사 로고가 뜬 다음 다음과 같은 에러메시지를 내며 멈추는 것을 확인할 수 있다.

단순한 COPY명령을 이용한 디스크 복사로는 원본 디스크의 비표준 포맷부분을 옮길 수 없어 체커에 걸려 실행되지 않는 것이다. 이제 위에서 말하는 “관리영역이 파괴되어 있어 사용 불능” 문제를 해결하는 방법을 설명한다.
그러면 봄버맨 본체를 살펴봅시다. 디버거를 기동해 “봄버맨”을 읽어들입시다.
A>DB
X68k Debugger v3.00 Copyright 1987-1993 SHARP/Hudson
Micro Processor Unit:16bit MC68000
Floating Point Co Processor:Softwere emulation.
-R B:¥BM.x, .PC
No Symbol file
PC=00076060 USP=000538C4 SSP=00008364 SF=0000 X:0 N:0 Z:0 V:0 C:0
HI:1 LS:0 CC:1 CS:0 NE:1 EQ:0 VC:1 VS:0 PL:1 MI:0 GE:1 LT:0 GT:1 LE:0 HS:1 LO:0
D 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
A 00075F60 000F9CA2 0003E1DC 0003F0E0 00076060 00000000 00000000 000538C4
pea (A5) ;$00000000(long $00FF05E4)
또, 읽어들일 때 (프로그램 실행시라고 생각하면 됩니다), 프로그램의 메모리 관리 포인터 어드레스가 a000075F60에 프로그램 끝 +1의 어드레스가 a1000F9CA2에 들어있습니다. 나오는 값은 각자의 시스템 환경에 따라 다를 수 있다. 위 값은 X68000XVI 12MB메모리탑재 모델에서 나온 값. 이것은 나중에 서치 부분에서 필요하므로 기억해 두세요.
pc는 프로그램 카운터이므로 그 프로그램이 시작하는 선두 번지고, A1이 프로그램 끝 번지+1이므로 (A1-1)-PC를 하면 프로그램의 용량이 나온다. ($F9CA2-1) – $76060 = $83C41 = (DEC)539713 <- BM.X의 용량과 같다.
여기서부터가 본론입니다. 그러면, 프로텍트의 체크등에 필요한 비표준 포맷 읽기는 Human68k등의 OS에서는 할 수 없습니다. “C=$20 H=$01 R=$03 N=$03″을 읽어들인다 같은 곡예는 할 수 없습니다. OS에서는 파일을 읽어들인다, 파일을 써넣는다와 같은 파일 단위로 밖에 할 수 없습니다 (그것이 MS-DOS와 Human68k의 특징입니다)
설마 프로텍트의 포맷에 걸린 부분의 파일을 읽어들인다…라는 건, 읽어들이는 시점에서 비표준 포맷에서는 금지되어있고요. 어떻게도 OS에서는 할 수 없기 때문에(라고 썼지만 할 필요가 없습니다), 플로피 디스크를 직접 읽어 봅시다. 하지만, 그것은 상당히 복잡한 프로그램 지식이 필요합니다.
하지만, X68000에는 매우 편리한 것이 준비되어있습니다. 그 이름을 “Input Output Call System” 줄여서 “iocs call”이라고 합니다.
그 콜을 사용하는 방법입니다만, 그 콜 번호를 D0레지스터에 대입하고(68000에는 D0~D7까지 데이터 레지스터가 있습니다. 모두 32비트 들어갑니다), “trap”이라는 명령을 실행하면 (그 Trap에도 0~15까지 종류가 있고, 각각 의미가 있습니다. 덧붙여 말하면 iocs call은 “Trap #$0f15“입니다), D0에 넣은 번호에 대응한 프로그램으로 날아가 처리를 자동으로 해줍니다. (여담입니다만, X68000의 $400번지로부터, 그 번호에 대응한 프로그램의 어드래스가 격납되어있습니다. 예를들면 $400번지에는 iocs Call의 0번에 대응하는 프로그램 어드레스가 $404에는 1번 어드레스가.. 라는 식으로 4 어드레스마다 어드레스가 격납되어있습니다. 이 어드레스를 벡터라고 합니다만, 이 벡터를 바꿔쓰는 것으로 자신의 프로그램으로 바꿔치기하는 것이 가능합니다.)
디스크를 읽어낸다가 iocs Call의 $46B_READ이므로, 보통 프로텍트를 건다고 하면 어디선가 D0에 $46을 대입하고 “trap #$0f”를 실행하고 있을 것입니다. 그러면, 프로그램 전체로부터 그 부분을 찾아봅시다. 하지만, 무척 크므로, 1바이트 1바이트씩 찾을 수는 없습니다. (찾아야만 하는 경우도 있습니다만) 하지만, 매우 편리한 기능이 디버거에는 있습니다. 그것은 “메모리 서치”입니다. 프로그램 속에서 어느 일정 데이터를 찾고, 그 데이터에 격납되어있는 어드레스를 표시해주는 녀석입니다. 그러면 사용법입니다만, 문법은 다음과 같습니다.
MS[size] range data : 메모리 내용 검색
이것이 디버거의 도움말의 서치 부분입니다. 자세하게 설명하자면, “MS”의 뒤에 서치할 데이터의 사이즈를 세트합니다. 1바이트 마다 서치하려면 “MSS”로, 1워드 마다(2바이트씩) 서치하려면 “MSW”로 1롱 워드마다(4바이트씩) 서치하려면 “MSL”이라고 합니다. [size]가 이것을 말하는 것입니다. 다음에 서치하는 범위를 설정합니다. 그것이 [range]입니다. 그것으로부터 서치하는 데이터군을 설정합니다. 그러면 예를 몇가지 소개합니다. (또, 디버거의 버전이 1인 사람은 “MS”가 아니라 “S”이므로 주의해주세요”).
예1
[$01][$05][$03][$f3][$d5]라는 데이터를 $40000-$4ffff까지 서치합니다.
-MSS 40000 4FFFF 01 05 03 f3 d5
예2
[$3f2d][$1535][$1234][$acdf][$7046]이라는 데이터를 $40000부터 $2000바이트분 서치합니다. (사이즈로 설정하는 경우는 데이터의 앞머리로 [L]을 붙입니다).
-MSW 40000 L2000 3f2d 1535 1234 acdf 7046
예3
[$70464e4f][$323c9050][$030f0501]이라는 데이터를 a0 레지스터에 설정되어있는 번지로부터 a1 레지스터에 설정되어있는 어드레스까지 서치합니다. (레지스터를 어드레스의 대신 대입하는 경우 레지스터 명의 앞머리로 [.]을 붙입니다. 어드레스 레지스터는 A0~A7까지 있습니다. 당연히 32비트 들어갑니다).
-MSL .a0 .a1 70464e4f 323c9050 030f0501
보너스
[$00000001][$00000002][$00000003]이라는 데이터를 pc레지스터에 설정되어있는 번지로부터 a1레지스터에 설정되어있는 어드레스까지 서치합니다. (현재 실행 사용하려는 명령의 번지가 격납되어있는 어드레스를 프로그램 카운터 어드레스(PC)라고 합니다. 서치 상에서 사용하려면 어드레스 레지스터와 같은 방법으로 합니다)
-MSL .pc .a1 1 2 3
(-MSL .pc .a1 00000001 00000002 00000003 과 동일합니다. 이렇게 생략할 수 있습니다)
아까 디스크 리드는 $46이라고 했습니다. 그리고 “Trap #$0f”이므로 어셈블러로 적으면 이렇게 됩니다.
moveq #$46, d0 $7046
trap #$0f $4e4f
오른쪽에 적혀있는 데이터열은 어셈블러 표기를 기계어로 변환한 것입니다. 그러면 위의 데이터를 “BM.x”로부터 찾아봅시다.
-MSW .PC .A1 7046 4e4f
00076156 00083B14
$76156 $83B14 두 곳에 [$7046][$4e4f]라는 데이터가 있다는 것입니다. 알겠나요? .pc .a1이라는 것은 프로그램의 선두부터 최후까지 서치. 라고 생각해도 됩니다. (사실은 .pc .a1-1이 맞지만요)
그러면 첫번째의 [$76156]근처를 살펴봅시다. 또, 역 어셈블(기계어를 어셈블러 표기로 변환해 표시함)은 “L”입니다.
-L76156-24moveq #$46,D0의 주소 $76156를 기준으로 분석을 위해 적당히 $24만큼 앞의 주소부터 표시
00076132 move.w #$9000, D1
00076136 moveq #$44, D0
00076138 trap #$0F
0007613A btst.l #$001D, D0
0007613E beq.s $000F06C2
00076140 move.w #$9070, D1 드라이브0 지정입니다.
(드라이브 1이면 $91이 되며 그것을 D1에 넣습니다)
00076144 move.l #$020A0001, D2 C=$0A H=$00 R=$01 N=$02를 읽어들입니다.
iocs call에서는 [N C H R]순서로 읽습니다.
그 데이터를 D2에 넣습니다.
0007614A move.l #$00001E00, D3 $1E00바이트 읽기. 그것을 D3에 넣습니다.
-L"L[주소범위]" 용법이므로 주소의 범위를 지정하지 않으면 8줄 보여주고 명령을 다시 입력해야한다.
00076150 lea $00082B18, A1 읽어들인 어드레스를 지정합니다. 그것을 A1에 넣습니다.
00076156 moveq #$46, D0 디스크 읽기 번호입니다.
00076158 trap #$0F ocs call 실행
0007615A andi.l #4D8FFFF00, D0 읽기가 정상 종료했는가?
00076160 bne.s $000F06C2 이상이라면 반복
00076162 rts 정상종료이므로 되돌아갑니다
⁞
이런 느낌입니다. 이것을 BASIC풍으로 쓰면 다음과 같이 됩니다.
1000 d1=&h9000 *드라이브 0 지정
1010 d0=&h44 *드라이브 상태를 얻는 콜 번호
1020 a=drive_sns *드라이브 상태를 얻음
1030 if a<>0 then 1000 *이상이라면 검사를 반복
1040 d1=&h9070 *드라이브 0 지정
1050 d2=&h020a0001 *읽기 위치
1060 d3=&h00001e00 *읽기 사이즈
1070 a1=read_buffer *읽기 장소를 지정
1080 d0=&h46 *읽기 콜 번호
1090 a=disk_read *디스크 읽기
1100 if a<>0 then 1000 *읽기가 이상이라면 반복
1110 return *원래 루틴으로 되돌아감
이런 느낌입니다. 그러면 BASIC 쪽의 프로그램에서 생각해봅시다. 그러면 어떻게 하면 좋을까요? 자주 “1100행을 지운다”라는 분이 계십니다만, 그랬다가는 프로텍트를 위해 디스크를 읽어버립니다. 가장 좋은 방법이라고는 생각할 수 없습니다. 그러면 어떻게 해야할까요? “1040행에 return을 한다”라는 것은 어떨까요? “1040행을 goto 1110″이라고해도 좋습니다.
그러면 어셈블러 판을 바꿔 써봅시다. 어셈블러 쓰기는 “A”입니다.
-A76140
00076140 move.w #$9070, D1
rts
00076142 sub.w $3C(A0,D2.w*4),D0
[.]을 눌러 종료합니다.
실은 이 봄버맨은 그 이상 포맷 부분에 세이브 데이터를 등록합니다. 다시말해, 이 프로텍트용의 이상 포맷은 X68000상에서 충분히 재현 할 수 있습니다.
그러면 두번째의 서치부분을 해석…하고 싶습니다만, 실은 두번째의 어드레스 부분은 세이브한 데이터를 로드하기 위한 루틴입니다. 다시말해서 위 부분에서 “봄버맨”의 프로텍트가 제거된 것입니다.
그러면 이 데이터를 써넣읍시다.
-R B:¥BM.x .PC
라고 하고 읽은 뒤위 명령을 실행하면 다시 수정되기 전 내용을 디버거가 읽어오므로, 애써 수정한 게 무효화된다. 따라서 이 내용은 삭제한다. 이렇게 입력해 주세요.
-W B:¥BM.x .PC, .A1-1
이것으로 프로텍트를 제거한 “BM.x”가 디스크에 써졌습니다. (절대 마스터 디스크에 쓰지 말고 백업한 디스크에 해주세요).
그러면, 기동해봅시다. 시스템 소프트웨어의 오프닝이 시작되고… 다라란랏랏랏랏라안 하고 음악이 흐르나요? 이것으로 프로텍트가 걸려있지 않은 “봄버맨”이 만들어졌습니다.







댓글 남기기