SCM player skins Line Up: [EUD 기초] EUD 입문자 가이드

2/25/2015

[EUD 기초] EUD 입문자 가이드


0. 선행 지식

스타크래프트를 실행하면 install.exe / stardat.mpq / broodat.mpq / patch_rt.mpq / battle.snp / standard.snp 등의 파일들을 불러오는데 여기서 파일에 저장되어 있는, 스타크래프트와 관련된 모든 데이터들은 모조리 메모리 상에 올라갑니다. 그리고 이렇게 메모리 상에 올라간 데이터들을 데스트리거를 이용해 조작할 수 있는데, 이러한 기술이 EUD입니다. 따라서 EUD를 알아보기에 앞서 스타크래프트의 데이터들이 메모리 상에 어떻게 저장되있고, 어떤 식으로 정렬되어 있는지 알아봅시다.


0-1. 메모리

메모리 상에 저장되어 있는 데이터들은 모두 주소값이 있습니다. 이러한 주소값들은 16진수로 나타내는데 스타크래프트에서 다루는 데이터들은 모두 0~0xFFFFFFFF(=2^32-1) 범위에, 각 주소값마다 0~0xFF(=2^8-1)의 값(1byte)을 저장합니다. 예를 들어 유닛코드가 0인 마린의 지상 무기 데이터 값은 0x006636B8에 저장되어 있습니다. 스타크래프트 상의 주소값들을 살펴보기 위한 툴로는 Art Money 또는 Cheat Engine 등이 있습니다.



0-2. 리틀 엔디안(Little Endian)

아까 하나의 주소값에는 1byte 크기 만큼의 값이 저장된다고 하였습니다. 그렇다면 1byte보다 큰(255보다 큰) 값들은 어떻게 저장할까요? 답은 간단하게 1byte를 여러 개 연달아서 값을 지정하면 더 큰 값을 저장할 수 있을 것이다. 메모리에서 데이터를 읽을 때, 2byte에 걸쳐 저장된 값을 읽을 때는 word, 4byte에 걸쳐 저장된 값을 읽을 때는 dword라 합니다.
그런데 인텔 CPU 계열에서는 저장된 값들을 읽을 때 값들의 순서를 뒤집어서 읽습니다. 즉, 아래 그림에서 0x6636B8부터 0x6636BB까지의 값들을 읽어보면 00 02 04 82  0x82040200이 됩니다. 한번 더 예를 들어 0x6636BC부터 0x6636BF까지의 값들을 읽어보면 07 82 0B 0D → 0x0D0B9207이 됩니다. 이러한 방식으로 데이터들을 읽는 것을 리틀 엔디안(Little Endian)이라 부릅니다.










1. EUD란?

EUD는 Extended Unit Death를 뜻하는 말로, 227보다 높은 유닛의 ID(원래는 스타크래프트의 유닛은 0부터 227까지)의 파괸된 수(Death)를 조절하여 데이터 값을 조작하는 기술입니다. 즉, EUD를 사용하면 스타크래프트 상의 데이터들을 변경 및 조작이 가능합니다.


1-1. EUD의 원리

데스트리거는 유닛의 데스값을 조절하는 트리거입니다. 즉, 어떤 플레이어의 유닛의 데스값이 저장되있는 주소값의 데이터들을 조작할 수 있다는 뜻입니다. 이를 거꾸로 생각하면, 주소값을 알 수 있다면 그 주소값이 어떤 플레이어의 유닛의 데스값인지 알 수 있을 겁니다. 그 공식은 다음과 같습니다.

(원하는 주소값) : 0x58A364 + (플레이어)×4 + (유닛번호)×48
여기서 플레이어 값에 4가 곱해지기 때문에 EUD는 4byte로 밖에 읽지 못합니다. 그렇기 때문에 0x6636B8~0x6636BB의 주소값을 EUD값으로 바꾸면 모두 똑같이 플레이어 P2, 유닛 ID 18535입니다. 
(물론 EPD를 사용하면 1byte로 읽을 수 있습니다.)



1-2. EUD의 한계

EUD는 스타크래프트 내에 존재하는 데이터를 변경만 하는 것일 뿐, 아예 새로운 것을 만들거나, 데이터 자체를 삭제시키는 것은 불가능합니다. 물론, 최근들어 GRP를 바꿔서 기존 스타크래프트 유닛의 외형에서 벗어나는것이 가능해졌고, 유닛의 외형은 물론 무기 이펙트가 그래픽등, 또한 아이콘과 문자열마저 바꾸는 경지에 이르렀기에 그만큼 EUD로 표현할 수 있는 것은 더욱 많아졌지만, 그것은 그저 한동안 숨어있다가 짜잔 하고 보여진 것에 불과합니다.









2. EUD 트리거 만들어보기

맵 에디터는 scmdraft2와 플러그인인 TrigEditPlus를 사용하고 EUD Trig를 이용하여 플레이어와 유닛 ID 값을 구할 것입니다. 툴들은 본 블로그 자료 게시판에서 다운받아주세요. (scmdraft2는 액션부와 조건부 제한이 풀린 것을 이용해주세요.) (TrigEditPlus는 http://cafe.naver.com/edac/34966에서 다운이 가능합니다.)


2-1. 오프셋 구하기

오프셋이란 것은 기준이 되는 주소값을 일컫습니다. 스타크래프트는 데이터들을 아무렇게나 메모리에 저장해두지 않습니다. 일정한 규칙과 범위를 두고 주소값을 지정하여 데이터들을 저장합니다. 이 때, 특정한 데이터들을 저장해두는 주소값들 중 가장 첫번째를 오프셋이라 합니다. 오프셋으로부터 데이터들이 일정한 규칙과 범위를 두고 차례데로 정렬이 되어 있습니다. 따라서 오프셋을 안다면 내가 변경하고 싶은 데이터의 주소값을 오프셋으로부터 쉽게 찾아낼 수 있습니다.
(EUD Trig에서 그 기능도 제공합니다.)
주소값을 구하는 가장 확실한 방법은 스타크래프트를 Art Money 등과 같은 메모리 에디터를 이용하여 직접 주소값을 찾는 것입니다. 하지만 이런 방법은 귀찮고, 헷갈리니 여러 사이트나 자료 등을 참고하는 것이 현명한 선택입니다. 다음은 추천 사이트 및 자료 입니다.

  • EUD DB  
대부분의 오프셋들이 저장되어 있는 데이터베이스 사이트. 단점이라면 영어로 되어 있습니다.

  • DEls 
DatEdit 프로그램에 나와있는 값들의 오프셋을 쉽게 찾을 수 있는 swf파일입니다. 인투더맵의 혈랑의추억님이 제작하셨습니다.

  • 스타 에디터 아카데미 
우리나라 대부분의 EUD 연구가 이루어지고, 맵 제작자들이 활동하는 카페입니다. 모르는 오프셋은 여기서 찾아보거나 질문을 달도록 합시다.

  • EUD 초심자들을 위한 EUD 계산&정보모음
스타 에디터 아카데미의 Raszagal님께서 만드신 엑셀 파일. 상당히 유용합니다.



2-2. EUD Trig 사용법




① Memoey Offset : 오프셋 주소값을 입력합니다.
② Object ID : 오프셋에서 몇 만큼 이동할지 수를 입력합니다.
③ Length : 데이터의 크기를 입력합니다.
④ Use Extended Player Deaths : EPD를 사용할지 여부를 결정합니다.
⑤  계산 스위치 : 플레이어와 유닛 ID를 계산 또는 반대로 플레이와 유닛 ID를 이용해 오프셋을 계산합니다.
⑥ Player Number : 해당 주소값의 EUD 플레이어 값입니다.
⑦ Unit ID : 해당 주소값의 EUD 유닛 ID 값입니다.



2-3. (ex) 유닛의 지상무기를 변경해보자
유닛의 지상무기 오프셋은 다음과 같습니다.

오프셋 : 0x6636B8
주소값 : 0x6636B8 + (1byte) * (유닛 ID)
데이터 크기 : 1byte
데이터 값 : 무기 ID
EUD Trig를 켜서 다음과 같이 입력해봅시다. 저는 유닛 ID가 2인 벌쳐의 지상무기를 변경하겠습니다. 데이터의 크기는 1byte이니 Length를 1로 설정하고, 벌쳐의 유닛 ID는 2이므로 Object ID에 2를 입력합니다. 
(유닛 ID나 무기 ID 등은 DatEdit 등을 이용하여 쉽게 알아낼 수 있습니다.)



그리고 계산하면 플레이어 넘버가 P2, Unit ID가 18535가 뜨는군요. 그리고 Byte Offset에 00 00 00 00 이라 뜨네요. 이것이 무엇을 의미할까요? 



1-1에서 EUD는 4byte씩 읽는다고 했습니다. 그러므로 차례대로 4byte만큼의 데이터들의 주소값들을 EUD로 나타내면 모두 똑같습니다. 즉, 0x6636B8~0x6636BB는 EUD값이 같습니다. 그런데 그중 0x6636BA는 0x6636B8로 부터 3번째에 있는 값입니다. 4byte씩 끊는 데이터 중 3번째라는 뜻이죠. 아래 Art Money를 봅시다.



아까 메모리에 있는 값들은 리틀 엔디안 방식으로 데이터들을 읽는다고 하였습니다. 그러므로 빨간 네모상자에 적혀 있는 값은 주소값 0x6636B8에서 읽으면 0x40000입니다. 따라서 벌쳐의 지상무기 주소값인 0x6636BA(0x6636B8+0x2)에 저장된 값을 변경하기 위해서는 변경하려는 값에 0x10000=65536을 곱해야합니다. 이를 규칙화시키면 다음과 같습니다.


00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
값에 1(=0x1)을 곱한다.

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
값에 256(=0x100)을 곱한다.

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
밸류에 65536(=0x10000)을 곱한다.

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
밸류에 16777216(=0x1000000)을 곱한다.


적당히 벌쳐의 지상무기를 무기 ID가 8인 Helfire Missile Pack으로 바꿔봅시다. 원래 벌쳐의 지상무기의 ID는 2이므로 8로 바꾸기 위해서는 6만큼을 더해야합니다. 그리고 Byte Offset에 따라 65536(=0x10000)를 곱하여 393216만큼의 값을 더하여야 합니다. TrigEditPlus로 다음과 같은 트리거를 추가합니다.

SetDeaths(P2, Add, 393216, 18535);

그리고 w런쳐로 스타크래프트 실행하여 확인해봅시다. 다음과 같이 잘 적용되있음을 확인할 수 있습니다.









3. 참고 및 추천 사이트





댓글 없음:

댓글 쓰기