이번 시간에는 드디어 python을 사용할 예정이다.
2부에서 찾았던 주소들을 python으로 읽기 전에 주소들을 다시한번 정리하자.
================
마리오의 x위치는 0086 006D이다
마리오의 y위치는 00CE
마리오의 x속도는 0057
마리오의 y속도는 009F
마리오의 상태는 0754 0756 : 꼬마는 10 성인은 01 불쏘는 성인은 02
각 몬스터의 x위치는 0087 0088 0089 008A 008B
006E 006F 0070 0071 0072
각 몬스터의 y위치는 00CF 00D0 00D1 00D2 00D3
각 몬스터의 종류는 0016 0017 0018 0019 001A
점수: 07DD ~ 07E4 (BCD 코드)
시간: 07F8 ~ 07FA (BCD 코드)
앞으로 나아간 정도: 071B 071C
stage: 075C 075F
입력 커맨드: 06FC
========================
python에서 특정 프로세스의 메모리를 읽거나 쓰는 다양한 방법이 존재하지만,
ReadWriteMemory 라는 라이브러리를 이용하는 것이 가장 간단하고 직관적이다.
아래 링크를 참조해서 다운받고 사용법을 익히자.
https://pypi.org/project/ReadWriteMemory/
from ReadWriteMemory import ReadWriteMemory
rwm = ReadWriteMemory()
process = rwm.get_process_by_name('VirtuaNES.exe')
process.open()
base_address = 0x0059E3B0
offset = 0x07FA
address = base_address + offset
time = process.read(address)
print(time)
위 코드는 마리오 게임의 남은시간의 일의 자리 숫자를 출력하는 코드이다.
메모리 뷰어에서 보았던 주소들은 사실 위 base address인 0x0059E3B0에서 시작한다.
따라서 지난 글에서 찾았던 다양한 값들의 주소는 base address에 더해서 주소를 구해야한다.(offset)
process.write(address, 9)
해당 주소에 직접 쓸 수도 있다.
실행하면 남은 시간의 일의 자리 숫자가 9로 바뀐다.
자 이제 요리조리 해서 시각화를 하자.
먼저, 정적 정보의 시각화를 해본다.
def get_name_table(self):
name_table = np.zeros((26,16))
for offset in self.offsets['name_table']:
address = self.base_address + offset
value = self.process.read(address)
value = value.to_bytes(4, 'big')[3]
i = (offset-0x0500) // 16
j = (offset-0x0500) % 16
name_table[i, j] = value
name_table_reshaped = np.zeros((13,32))
name_table_reshaped[:,:16] = name_table[:13,:]
name_table_reshaped[:,16:] = name_table[13:,:]
return name_table_reshaped
def visualize_name_table(self):
name_table = self.get_name_table()
name_table = name_table.astype(np.uint8)
name_table_image = cv2.applyColorMap(name_table, cv2.COLORMAP_VIRIDIS)
name_table_image = cv2.resize(name_table_image, (None, None), fx=20, fy=20, interpolation=cv2.INTER_NEAREST)
cv2.imshow('', name_table_image)
cv2.waitKey()
현재 맵이 numpy array로 변형되었고, 위 처럼 시각화 되었다.
원본은 위 이미지와 같다.
이제 저 위 정적 정보 위에 마리오를 올려보자.
마리오의 위치가 실시간으로 잘 반영된다.
몬스터를 나타내고, 카메라가 보고 있는 부분만 크롭하도록 하자..
이제 몬스터도 잘 보이고 현재 화면 기준으로 카메라가 잘 따라온다.
가끔 이 상태로 플레이하다 보면 개발자가 만든 실수나 이스터 에그를 발견할 수 있다.
보이지 않는 몬스터의 영혼(?)들을 볼 수 있다;;
4부에서 계속...
'기타 잡 코딩' 카테고리의 다른 글
iptables 명령어란? (0) | 2023.03.19 |
---|---|
슈퍼마리오 1을 플레이하는 AI를 만드는 방법(4) (1) | 2021.07.11 |
슈퍼마리오 1을 플레이하는 AI를 만드는 방법(2) (0) | 2021.07.09 |
슈퍼마리오 1을 플레이하는 AI를 만드는 방법 (0) | 2021.07.07 |
폴란드 테트리스를 플레이하는 AI를 만드는 방법(2) (0) | 2021.07.06 |