ref: ec098d1a03e28e07c3bbd3174b5f02b713c24b6f
parent: 160acfa2967e898f97ba2b92e8602146bdf5b714
author: Bryan Bishop <[email protected]>
date: Tue Feb 26 16:49:54 EST 2013
various helper functions for the vba interface New vba.py features include: * get_memory_at * get_memory_range * set_memory_at Also, the "crystal" class has a number of specialty helpers: * crystal.walk_through_walls * crystal.get_player_name * crystal.get_map_name * crystal.get_xy * crystal.nstep (which sets memory each step by calling certain * functions, like walk_through_walls) * crystal.is_in_battle * crystal.get_gender
--- a/extras/vba.py
+++ b/extras/vba.py
@@ -54,12 +54,13 @@
# or why not the other way around?
vba.set_state(vba.load_state("unknown-delete-me"))
- registers = vba.get_registers()
+ vba.get_memory_at(0xDCDA)
+ vba.set_memory_at(0xDCDB, 0xFF)
+ vba.get_memory_range(0xDCDA, 10)
TOOD:
[ ] set a specific register
[ ] get a specific register
- [ ] write value at address
[ ] breakpoints
[ ] vgm stuff
[ ] gbz80disasm integration
@@ -71,6 +72,11 @@
import sys
from array import array
+# for converting bytes to readable text
+from chars import chars
+
+from map_names import map_names
+
# for _check_java_library_path
from java.lang import System
@@ -157,7 +163,7 @@
for each in buttons:
result |= button_masks[each]
-
+
print "button: " + str(result)
return result
@@ -208,6 +214,12 @@
# just some aliases for step_until_capture
run = go = step_until_capture
+def translate_chars(charz):
+ result = ""
+ for each in charz:
+ result += chars[each]
+ return result
+
def _create_byte_buffer(data):
"""
Converts data into a ByteBuffer. This is useful for interfacing with the Gb
@@ -310,7 +322,7 @@
def get_rom():
"""
- Returns the ROM in bytes.. in a string.
+ Returns the ROM in bytes.
"""
rom_array = jarray.zeros(Gb.ROM_SIZE, "i")
Gb.getROM(rom_array)
@@ -318,7 +330,7 @@
def get_ram():
"""
- Returns the RAM in bytes in a string.
+ Returns the RAM in bytes.
"""
ram_array = jarray.zeros(Gb.RAM_SIZE, "i")
Gb.getRAM(ram_array)
@@ -332,14 +344,20 @@
def get_memory():
"""
- Returns memory in bytes in a string.
+ Returns memory in bytes.
"""
- raise NotImplementedError("dunno how to calculate memory size")
- # memory_size = ...
+ memory_size = 0x10000
memory = jarray.zeros(memory_size, "i")
Gb.getMemory(memory)
return RomList(memory)
+def set_memory(memory):
+ """
+ Sets memory in the emulator. Use get_memory() to retrieve the current
+ state.
+ """
+ Gb.writeMemory(memory)
+
def get_pixels():
"""
Returns a list of pixels on the screen display. Broken, probably. Use
@@ -371,7 +389,28 @@
Read an integer at an address.
"""
return Gb.readMemory(address)
+get_memory_at = read_memory
+def get_memory_range(start_address, byte_count):
+ """
+ Returns a list of bytes.
+
+ start_address - address to start reading at
+ byte_count - how many bytes (0 returns just 1 byte)
+ """
+ bytez = []
+ for counter in range(0, byte_count):
+ byte = get_memory_at(start_address + counter)
+ bytez.append(byte)
+ return bytez
+
+def set_memory_at(address, value):
+ """
+ Sets a byte at a certain address in memory. This directly sets the memory
+ instead of copying the memory from the emulator.
+ """
+ Gb.setMemoryAt(address, value)
+
def press(buttons, steplimit=1):
"""
Press a button. Use steplimit to say for how many steps you want to press
@@ -385,4 +424,161 @@
number = buttons
for step_counter in range(0, steplimit):
Gb.step(number)
+
+class crystal:
+ """
+ Just a simple namespace to store a bunch of functions for Pokémon Crystal.
+ """
+
+ @staticmethod
+ def walk_through_walls_slow():
+ memory = get_memory()
+ memory[0xC2FA] = 0
+ memory[0xC2FB] = 0
+ memory[0xC2FC] = 0
+ memory[0xC2FD] = 0
+ set_memory(memory)
+
+ @staticmethod
+ def walk_through_walls():
+ """
+ Lets the player walk all over the map. These values are probably reset
+ by some of the map/collision functions when you move on to a new
+ location, so this needs to be executed each step/tick if continuous
+ walk-through-walls is desired.
+ """
+ set_memory_at(0xC2FA, 0)
+ set_memory_at(0xC2FB, 0)
+ set_memory_at(0xC2FC, 0)
+ set_memory_at(0xC2FD, 0)
+
+ @staticmethod
+ def nstep(steplimit=500):
+ """
+ Steps the CPU forward and calls some functions in between each step,
+ like to manipulate memory. This is pretty slow.
+ """
+ for step_counter in range(0, steplimit):
+ crystal.walk_through_walls()
+ step()
+
+ @staticmethod
+ def get_map_group_id():
+ """
+ Returns the current map group.
+ """
+ return get_memory_at(0xdcb5)
+
+ @staticmethod
+ def get_map_id():
+ """
+ Returns the map number of the current map.
+ """
+ return get_memory_at(0xdcb6)
+
+ @staticmethod
+ def get_map_name():
+ """
+ Figures out the current map name.
+ """
+ map_group_id = crystal.get_map_group_id()
+ map_id = crystal.get_map_id()
+ return map_names[map_group_id][map_id]["name"]
+
+ @staticmethod
+ def get_xy():
+ """
+ (x, y) coordinates of player on map.
+ Relative to top-left corner of map.
+ """
+ x = get_memory_at(0xdcb8)
+ y = get_memory_at(0xdcb7)
+ return (x, y)
+
+ @staticmethod
+ def is_in_battle():
+ """
+ Checks whether or not we're in a battle.
+ """
+ return (get_memory_at(0xd22d) != 0) or crystal.is_in_link_battle()
+
+ @staticmethod
+ def is_in_link_battle():
+ return get_memory_at(0xc2dc) != 0
+
+ @staticmethod
+ def unlock_flypoints():
+ """
+ Unlocks different destinations for flying.
+
+ Note: this might start at 0xDCA4 (minus one on all addresses), but not
+ sure.
+ """
+ set_memory_at(0xDCA5, 0xFF)
+ set_memory_at(0xDCA6, 0xFF)
+ set_memory_at(0xDCA7, 0xFF)
+ set_memory_at(0xDCA8, 0xFF)
+
+ @staticmethod
+ def get_gender():
+ """
+ Returns 'male' or 'female'.
+ """
+ gender = get_memory_at(0xD472)
+ if gender == 0:
+ return "male"
+ elif gender == 1:
+ return "female"
+ else:
+ return gender
+
+ @staticmethod
+ def get_player_name():
+ """
+ Returns the 7 characters making up the player's name.
+ """
+ bytez = get_memory_range(0xD47D, 7)
+ name = translate_chars(bytez)
+ return name
+
+ @staticmethod
+ def set_partymon2():
+ """
+ This causes corruption, so it's not working yet.
+ """
+ memory = get_memory()
+ memory[0xdcd7] = 2
+ memory[0xdcd9] = 0x7
+
+ memory[0xdd0f] = 0x7
+ memory[0xdd10] = 0x1
+
+ # moves
+ memory[0xdd11] = 0x1
+ memory[0xdd12] = 0x2
+ memory[0xdd13] = 0x3
+ memory[0xdd14] = 0x4
+
+ # id
+ memory[0xdd15] = 0x1
+ memory[0xdd16] = 0x2
+
+ # experience
+ memory[0xdd17] = 0x2
+ memory[0xdd18] = 0x3
+ memory[0xdd19] = 0x4
+
+ # hp
+ memory[0xdd1a] = 0x5
+ memory[0xdd1b] = 0x6
+
+ # current hp
+ memory[0xdd31] = 0x10
+ memory[0xdd32] = 0x25
+
+ # max hp
+ memory[0xdd33] = 0x10
+ memory[0xdd34] = 0x40
+
+ set_memory(memory)