메모리 오프셋 <-> EUD 트리거 계산
[1] 계산 공식
여기서는 유틸자료실에 올려진 EUDTrig를 이용하여 메모리 오프셋과 EUD 트리거 사이의 공식을 알아 보기로 한다.
EUDTrig에서 1.15.2의 메모리 오프셋인 0x58A34C (5808972)를 Player number와 Unit ID를 뽑아내면 1과 0이 나온다.
이것을 기준값으로 두겠다.
먼저, 기준값에서 변수가 달라질 때 오프셋이 얼마나 달라지는지부터 알아 보도록 하자.
기준값에서의 Player number와 Unit ID가 1과 0인 것을 (1,0)이라고 표시하겠다.
그렇다면 (1,1)일때는 메모리 오프셋의 값이 어떻게 변할까? = 10진수 기준으로 48만큼 추가되었다.
(2,0)일때는? = 10진수 기준으로 4만큼 추가되었다.
이 상황에서 머리를 좀 굴려 보면, Unit ID는 1 증가할 때 마다 48만큼 추가되고 Player number는 1증가당 4추가되었으므로
[메모리 오프셋 = 기준값 + 48 x Unit ID + 4 x Player number] 가 된다.
이것을 좀 더 정리해 보면,
[메모리 오프셋 - 기준값 = 4 x {12 x (유닛아이디 + 플레이어 번호에서 1뺀 값 / 12)}] 가 된다.
간단히 말하면 메모리 오프셋에서 기준값을 뺀 값을 4로 나눈 다음,
다시 12로 나눠서 그것의 몫은 유닛아이디가 되고 나머지는 플레이어 번호-1이 되는데,
계산기를 기준으로 하면 정수는 유닛 아이디가 되고, 소수점 아래는 플레이어 번호에서 1을 뺀 것을 12로 나눈 값이 된다.
여기서 윈도우 계산기에 맞춰 오프셋에서 플레이어 번호와 유닛 아이디를 뽑아내는 공식을 만들어 보면,
유닛 아이디 = {(메모리 오프셋 - 기준값) / 48}에서 정수
플레이어 번호 = [{(메모리 오프셋 - 기준값) / 48} - 유닛 아이디] x 12 에서 정수 +1
그런데 이 계산을 보면, 다시 소수점이 나온다. 이것은 무엇을 뜻할까?
EUDTrig를 통해 다시 한번 삽질을 해 보니, EUDTrig 아래쪽의 Byte Offset 위치를 나타낸다는 것을 알 수 있었다.
(0x0059CCE4 ~ 0x0059CCE7의 플레이어 번호와 유닛 아이디는 같은데 ByteOffset만 다름)
1번째 바이트 = 0
2번째 바이트 = 0.25
3번째 바이트 = 0.5
4번째 바이트 = 0.75
즉, 여기까지의 모든 공식을 총정리해 보면 아래와 같다고 할 수 있겠다.
유닛 아이디 = {(메모리 오프셋 - 기준값) / 48} 에서 정수값
플레이어 번호 = [{(메모리 오프셋 - 기준값) / 48} - 유닛 아이디] x 12 에서 정수 +1
바이트 오프셋 = [[{(메모리 오프셋 - 기준값) / 48} - 유닛 아이디] x 12 - 플레이어 번호] x 4 에서 정수 +1
[2] 계산 공식 연습
공격 상태를 인식해 주는 오프셋인 0x0059CCE6 (5885158) 이 값에서
플레이어 번호, 유닛 아이디, 바이트 오프셋을 뽑아 내려면 어떻게 계산해야 할까?
여기서는 정확하고 보다 실용적인 윈도우 계산기를 통해 처음부터 끝까지 따라하면 계산할 수 있도록 설명하겠다.
1. 시작 메뉴 -> 모든 프로그램 -> 보조 프로그램 -> 계산기 실행
2. F5를 누르고 59CCE6 입력, F6을 누르면 10진수로 바뀜. 5885158 로 나왔다면,
3. - 5808972 엔터. 76186 라고 나왔다면,
4. / 48 엔터. 1587.2083333333333 라고 나왔다면, 유닛 아이디는 1587
5. - 1587 엔터. 0.208333333333 라고 나왔다면,
6. * 12 엔터. 2.5 라고 나왔다면, 플레이어 번호는 3
7. - 2 엔터. 0.5라고 나왔다면,
8. * 4 엔터. 2 라고 나왔다면, 바이트 오프셋은 3
굉장히 복잡해 보이지만, 몇 번 따라해 보면 이것도 별 것 아니다.
그래도 귀찮다면, 아래의 EUDTrig를 사용하여 알아 내도록 하자.
[3] EUD 자동 계산기 EUDTrig
계산 공식을 알면 뭐하나? 계산하기 귀찮은 것을..... 고맙게도 이 귀찮은 작업을 대신해 줄 계산기가 있다.
유틸자료실에 올려져 있는 EUDTrig를 사용하자.
다운받고 압축해제해서 EUDTrig를 실행한다. 그러면 아래 그림과 같이 뜰 것이다.
여기서 Memory Offset에는 확인한 메모리의 주소를 넣되 앞에 0x를 붙여 쓴다.
별도의 설정을 하지 않고 아래모양 화살표를 누르면 플레이어 번호와 유닛 아이디가 뜬다.
이것을 트리거로 뽑아 내려면 메뉴의 Exporter를 누른다.
그런 다음, 확인한 플레이어 번호와 유닛 아이디를 쓰자. (확인한 플레이어 번호에서 1빼야 트리거 파일이 잘 저장된다.)
만약 정확한 death값을 이미 알고 있다면 at least/at most/exactly 중에서 골라 쓰고,
실험할 목적으로 쓰겠다면 at least나 at most 중에서 골라 쓴다. (메모리 오프셋의 속성에 따라 범위가 통하지 않을 수도 있음)
Value는 트리거의 death값을 뜻하는데 0부터 4294967295까지의 값을 넣어 줄 수 있으면 좋겠지만,
EUDTrig에서는 최소 -2147483648부터 최대 +2147483647 까지된다.
그런다음 아래의 Output을 누르고 Add를 누르면 추가가 되고, Save를 누르면 저장된다.
*** (Unused님께서 추가해 주셨습니다.)
0 ~ 4294967295는 Unsigned Long에서 취할 수 있는 값으로써 부호를 따지지 않고,
-2147483648 ~ +2147483647은 Signed Long에서 취할 수 있는 값으로써 부호를 따진다.
즉, 0 ~ 2147483647까지는 둘다 같고, 2147483648 ~ 4294967295까지의 값이 -2147483648 ~ -1과 같다.
*** 캠페인 에디터나 SCMDraft 에서 편집할 때는 Unsigned Long이 아닌, Signed Long으로 입력해야 한다.
[4] 추가 내용
위의 계산 공식은 모두 EUDTrig를 이용하여 뽑아낸 것으로, 이것을 사용하면 플레이어의 번호는 아무리 높아 봤자 12이다.
그런데 스타에디트(번역) 게시판의 82번 글을 보면, 1.13버전일 때는 12이상의 값을 넣어야 조건부에서 업그레이드를 하게 만들 수 있었다.
이것들은 어떤 공식을 통해 나온 것인지 모르겠다. 플레이어 번호가 12를 주기로 달라지는 것인지, 버전이 달라서 그런 것인지는 몰라도, 적어도 EUDTrig의 공식에 의한 것이 아니라는 것은 확실하다.
첫댓글 이해가 잘 되는군요. 감사합니다.~
scmdreaft2도 트리거 파일 로드가능하나요? 그리고 메모리 오프셋이 정확히 뭔지 잘 이해가안가네요..제 머리가 나쁜탓도있겠지만 [3]번에서 계산기가 알아서 해주니까 [1]번과 [2]번은 궂이 할필요가 없나요?
메모리 오프셋은 아주 쉽게 설명하자면, 정보가 저장되는 메모리의 주소입니다. trg파일은 scmdraft에서는 쓸 수 없고 캠페인 에디터에서 쓸 수 있습니다. 이렇게 해서 불러온 트리거 파일을 저장한 맵 파일을 scmdraft로 열어도 되겠지만, scmdraft로는 death값을 10억 이상으로는 넣을 수 없습니다. 그래서 저는 큰 death값을 넣을 때는 scenario.chk 파일이라고 하는 녀석을 수정하는데요, 이건 복잡하니 아마도 스타포지로는 가능할 것 같네요. (death값의 최대는 42억 정도 됩니다.) 그리고 [1]번과 [2]번은 EUDTrig를 통해 나온 것이므로 그것의 원리를 알아보자는 정도가 되겠습니다.
아아..그리고 Exporter를 누른 다음 Player는 나온값에서 -1 Value는 Player -1를 해서 나온 값과 동일하게 적는건가요?
Exporter의 Player는 EUDTrig 아래쪽의 Player에서 1을 뺀 값을 적어야 합니다. 그리고 Value는 death값을 뜻하는데, 그림에서는 0으로 넣었습니다. 본문에 Value에 대한 설명이 없었군요. 방금 추가했습니다.^^
플레이어 번호를 1빼는 이유는 Player 1일 경우 플레이어 번호가 실제로는 0번으로 기록되기 때문입니다. (scenario.chk에서 TRIG의 플레이어 번호)
unsigned 4294967295와 signed -1의 값이 서로 같아요. (0xFFFFFFFF)
본문 글 수정함..
메모리 에디터에서 확인한 결과, 플레이어1의 마린이 죽은 횟수를 나타내는 오프셋에서 4만큼 추가된 곳이 플레이어2의 마린이 죽은 횟수를 나타내는 곳이었고, 48만큼 추가된 곳이 플레이어1의 고스트가 죽은 횟수를 나타내는 오프셋이었습니다. 여기서 나온 공식을 프로그램으로 만든 것이 EUDTrig인 것 같습니다. 그리고 아직 정확히는 모르겠지만, 플레이어 13 이상부터는 각 플레이어의 상태가 플레이어1~12 사이와 일치하는 것 같았습니다. 1.13버전의 번역된 EUD 자료와 대조해 보니, 아마도 13이상의 플레이어를 써야 플레이어1~12의 상태를 인식하거나 바꿔줄 수 있는 것 같습니다.
공격 상태를 인식해 주는 오프셋으로 계산을 하다 보니, EUDTrig의 밑에 나오는 Byte Offset을 어떻게 계산하는가까지 알게 되서 본문에 추가하였습니다. Byte Offset은 같은 플레이어 번호, 같은 유닛 아이디를 가진 4개의 주소가 1바이트씩 각각 다른 기능을 할 때, 이것을 구분해 주기 위해 표시한 몇번째 바이트냐를 나타내는 값입니다. 그런데 이것을 EUD에서 사용하기 위해서는 같은 플레이어 번호와 같은 유닛 아이디를 가지고 있기 때문에, 바이트의 위치가 첫번째가 아닐 경우에는 4개의 바이트의 값을 모두 읽어야 그것이 데스값이 됩니다.
예를 들어, 공격 상태 인식 EUD에서는 3번째 바이트를 써서 그 곳을 03으로 두는데, 그것을 4바이트 단위로 1~4번째 바이트를 모두 읽어 내면, 196608 이런 값을 가집니다. 즉, 이것이 데스값이 되고, 바이트의 위치는 데스값으로 계산될 수 없습니다.