diff options
| author | Bryan Bishop <kanzure@gmail.com> | 2013-09-09 02:04:47 -0500 | 
|---|---|---|
| committer | Bryan Bishop <kanzure@gmail.com> | 2013-09-09 02:04:47 -0500 | 
| commit | 54057bc762b955a4c8924fa951ebf2faadca16a9 (patch) | |
| tree | 384eb794ec4d454155e98fb04a5eb0b26a4d34b8 | |
| parent | 709850fff5ee7c8f6bff61a2b0f3b23d4954dcac (diff) | |
strip out jython garbage from vba.py
| -rw-r--r-- | pokemontools/vba/vba.py | 609 | 
1 files changed, 8 insertions, 601 deletions
| diff --git a/pokemontools/vba/vba.py b/pokemontools/vba/vba.py index e2d1168..00bde25 100644 --- a/pokemontools/vba/vba.py +++ b/pokemontools/vba/vba.py @@ -1,79 +1,14 @@  # -*- coding: utf-8 -*-  """ -vba-clojure (but really it's jython/python/jvm) - -This is jython, not python. Use jython to run this file. Before running this -file, some of the dependencies need to be constructed. These can be obtained -from the vba-clojure project. -    sudo apt-get install g++ libtool openjdk-6-jre openjdk-6-jdk libsdl1.2-dev mercurial ant autoconf jython - -    export JAVA_INCLUDE_PATH=/usr/lib/jvm/java-6-openjdk-amd64/include/ -    export JAVA_INCLUDE_PATH2=/usr/lib/jvm/java-6-openjdk-amd64/include/ - -    hg clone http://hg.bortreb.com/vba-clojure -    cd vba-clojure/ -    ./dl-libs.sh -    cd java/ -    ant all -    cd .. -    autoreconf -i -    ./configure -    make -    sudo make install - -Make sure vba-clojure bindings are in $CLASSPATH: -    export CLASSPATH=$CLASSPATH:java/dist/gb-bindings.jar - -Make sure vba-clojure is available within "java.library.path": -    sudo ln -s \ -      $HOME/local/vba-clojure/vba-clojure/src/clojure/.libs/libvba.so.0.0.0 \ -      /usr/lib/jni/libvba.so - -(In the above command, substitute the first path with the path of the vba-clojure -directory you made, if it is different.) - -Also make sure VisualBoyAdvance.cfg is somewhere in the $PATH for VBA to find. -A default configuration is provided in vba-clojure under src/. - -Usage (in jython, not python): -    import vba - -    # activate the laser beam -    vba.load_rom("/path/to/baserom.gbc") - -    # make the emulator eat some instructions -    vba.nstep(300) - -    # save the state because we're paranoid -    copyrights = vba.get_state() -    # or ... -    vba.save_state("copyrights") -    # >>> vba.load_state("copyrights") == copyrights -    # True - -    # play for a while, then press F12 -    vba.run() - -    # let's save the game again -    vba.save_state("unknown-delete-me") - -    # and let's go back to the other state -    vba.set_state(copyrights) - -    # or why not the other way around? -    vba.set_state(vba.load_state("unknown-delete-me")) - -    vba.get_memory_at(0xDCDA) -    vba.set_memory_at(0xDCDB, 0xFF) -    vba.get_memory_range(0xDCDA, 10) +VBA automation  """  import os  import sys  import re -from array import array  import string  from copy import copy +  import unittest  # for converting bytes to readable text @@ -81,22 +16,6 @@ from pokemontools.chars import chars  from pokemontools.map_names import map_names -# for _check_java_library_path -from java.lang import System - -# for passing states to the emulator -from java.nio import ByteBuffer - -# For getRegisters and other times we have to pass a java int array to a -# function. -import jarray - -# load in the vba-clojure bindings -import com.aurellem.gb.Gb as Gb - -# load the vba-clojure library -Gb.loadVBA() -  import keyboard  # just use a default config for now until the globals are removed completely @@ -109,131 +28,13 @@ rom_path = config.rom_path  if not os.path.exists(rom_path):      raise Exception("rom_path is not configured properly; edit vba_config.py? " + str(rom_path)) -def _check_java_library_path(): -    """ -    Returns the value of java.library.path. - -    The vba-clojure library must be compiled -    and linked from this location. -    """ -    return System.getProperty("java.library.path") +import vba_wrapper -class RomList(list): +vba = vba_wrapper.VBA(rom_path) +registers = vba_wrapper.core.registers.Registers(vba) -    """ -    Simple wrapper to prevent a giant rom from being shown on screen. -    """ - -    def __init__(self, *args, **kwargs): -        list.__init__(self, *args, **kwargs) - -    def __repr__(self): -        """ -        Simplifies this object so that the output doesn't overflow stdout. -        """ -        return "RomList(too long)" - -button_masks = { -    "a": 0x0001, -    "b": 0x0002, -    "r": 0x0010, -    "l": 0x0020, -    "u": 0x0040, -    "d": 0x0080, -    "select":   0x0004, -    "start":    0x0008, -    "restart":  0x0800, -    "listen":       -1, # what? -} - -# useful for directly stating what to press -a, b, r, l, u, d, select, start, restart = "a", "b", "r", "l", "u", "d", "select", "start", "restart" - -def button_combiner(buttons): -    """ -    Combines multiple button presses into an integer. - -    This is used when sending a keypress to the emulator. -    """ -    result = 0 - -    # String inputs need to be cleaned up so that "start" doesn't get -    # recognized as "s" and "t" etc.. -    if isinstance(buttons, str): -        if "restart" in buttons: -            buttons = buttons.replace("restart", "") -            result |= button_masks["restart"] -        if "start" in buttons: -            buttons = buttons.replace("start", "") -            result |= button_masks["start"] -        if "select" in buttons: -            buttons = buttons.replace("select", "") -            result |= button_masks["select"] - -        # allow for the "a, b" and "a b" formats -        if ", " in buttons: -            buttons = buttons.split(", ") -        elif " " in buttons: -            buttons = buttons.split(" ") - -    if isinstance(buttons, list): -        if len(buttons) > 9: -            raise Exception("can't combine more than 9 buttons at a time") - -    for each in buttons: -        result |= button_masks[each] - -    #print "button: " + str(result) -    return result - -def load_rom(path=None): -    """ -    Starts the emulator with a certain ROM. - -    Defaults to rom_path if no parameters are given. -    """ -    if path == None: -        path = rom_path -    try: -        root = load_state("root") -    except: -        # "root.sav" is required because if you create it in the future, you -        # will have to shutdown the emulator and possibly lose your state. Some -        # functions require there to be at least one root state available to do -        # computations between two states. -        sys.stderr.write("ERROR: unable to read \"root.sav\", please run" -        " generate_root() or get_root() to make an initial save.\n") -    Gb.startEmulator(path) - -def shutdown(): -    """ -    Stops the emulator. Closes the window. - -    The "opposite" of this is the load_rom function. -    """ -    Gb.shutdown() - -def step(): -    """ -    Advances the emulator forward by one step. -    """ -    Gb.step() - -def nstep(steplimit): -    """ -    Step the game forward by a certain number of instructions. -    """ -    for counter in range(0, steplimit): -        Gb.step() - -def step_until_capture(): -    """ -    Loop step() until SDLK_F12 is detected. -    """ -    Gb.stepUntilCapture() - -# just some aliases for step_until_capture -run = go = step_until_capture +button_masks = vba_wrapper.core.VBA.button_masks +button_combiner = vba_wrapper.core.VBA.button_combine  def translate_chars(charz):      result = "" @@ -241,217 +42,6 @@ def translate_chars(charz):          result += chars[each]      return result -def _create_byte_buffer(data): -    """ -    Converts data into a ByteBuffer. - -    This is useful for interfacing with the Gb class. -    """ -    buf = ByteBuffer.allocateDirect(len(data)) -    if isinstance(data[0], int): -        for byte in data: -            buf.put(byte) -    else: -        for byte in data: -            buf.put(ord(byte)) -    return buf - -def set_state(state, do_step=False): -    """ -    Injects the given state into the emulator. - -    Use do_step if you want to call step(), which also allows -    SDL to render the latest frame. Note that the default is to -    not step, and that the screen (if it is enabled) will appear -    as if it still has the last state loaded. This is normal. -    """ -    Gb.loadState(_create_byte_buffer(state)) -    if do_step: -        step() - -def get_state(): -    """ -    Retrieves the current state of the emulator. -    """ -    buf = Gb.saveState() -    state = [buf.get(x) for x in range(0, buf.capacity())] -    arr = array("b") -    arr.extend(state) -    return arr.tostring() # instead of state - -def save_state(name, state=None, override=False): -    """ -    Saves the given state to save_state_path. - -    The file format must be ".sav" -    (and this will be appended to your string if necessary). -    """ -    if state == None: -        state = get_state() -    if len(name) < 4 or name[-4:] != ".sav": -        name += ".sav" -    save_path = os.path.join(save_state_path, name) -    if not override and os.path.exists(save_path): -        raise Exception("oops, save state path already exists: " + str(save_path)) -    else: -        # convert the state into a reasonable output -        data = array('b') -        data.extend(state) -        output = data.tostring() - -        file_handler = open(save_path, "wb") -        file_handler.write(output) -        file_handler.close() - -def load_state(name): -    """ -    Reads a state from file based on name. - -    Looks in save_state_path for a file -    with this name (".sav" is optional). -    """ -    save_path = os.path.join(save_state_path, name) -    if not os.path.exists(save_path): -        if len(name) < 4 or name[-4:] != ".sav": -            name += ".sav" -            save_path = os.path.join(save_state_path, name) -    file_handler = open(save_path, "rb") -    state = file_handler.read() -    file_handler.close() -    return state - -def generate_root(): -    """ -    Restarts the emulator and saves the initial state to "root.sav". -    """ -    shutdown() -    load_rom() -    root = get_state() -    save_state("root", state=root, override=True) -    return root - -def get_root(): -    """ -    Loads the root state. - -    (Or restarts the emulator and creates a new root state.) -    """ -    try: -        root = load_state("root") -    except: -        root = generate_root() - -def get_registers(): -    """ -    Returns a list of current register values. -    """ -    register_array = jarray.zeros(Gb.NUM_REGISTERS, "i") -    Gb.getRegisters(register_array) -    return list(register_array) - -def set_registers(registers): -    """ -    Applies the set of registers to the CPU. -    """ -    Gb.writeRegisters(registers) -write_registers = set_registers - -def get_rom(): -    """ -    Returns the ROM in bytes. -    """ -    rom_array = jarray.zeros(Gb.ROM_SIZE, "i") -    Gb.getROM(rom_array) -    return RomList(rom_array) - -def get_ram(): -    """ -    Returns the RAM in bytes. -    """ -    ram_array = jarray.zeros(Gb.RAM_SIZE, "i") -    Gb.getRAM(ram_array) -    return RomList(ram_array) - -def say_hello(): -    """ -    Test that the VBA/GB bindings are working. -    """ -    Gb.sayHello() - -def get_memory(): -    """ -    Returns memory in bytes. -    """ -    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 screenshot() instead. -    """ -    sys.stderr.write("ERROR: seems to be broken on VBA's end? Good luck. Use" -    " screenshot() instead.\n") -    size = Gb.DISPLAY_WIDTH * Gb.DISPLAY_HEIGHT -    pixels = jarray.zeros(size, "i") -    Gb.getPixels(pixels) -    return RomList(pixels) - -def screenshot(filename, literal=False): -    """ -    Saves a PNG screenshot to the file at filename. - -    Use literal if you want to store it in the current directory. -    Default is to save it to screenshots/ under the project. -    """ -    screenshots_path = os.path.join(project_path, "screenshots/") -    filename = os.path.join(screenshots_path, filename) -    if len(filename) < 4 or filename[-4:] != ".png": -        filename += ".png" -    Gb.nwritePNG(filename) -    print "Screenshot saved to: " + str(filename) -save_png = screenshot - -def read_memory(address): -    """ -    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, holdsteps=1, aftersteps=1):      """      Press a button. @@ -473,18 +63,6 @@ def press(buttons, holdsteps=1, aftersteps=1):          for step_counter in range(0, aftersteps):              Gb.step(0) -def get_buttons(): -    """ -    Returns the currentButtons[0] value - -    (an integer with bits set for which -    buttons are currently pressed). -    """ -    return Gb.getCurrentButtons() - -class State(RomList): -    name = None -  class Recording:      def __init__(self):          self.frames = [] @@ -499,7 +77,7 @@ class Recording:          """          Saves the current state.          """ -        state = State(get_state()) +        state = bytearray(get_state())          state.name = name          self.states[self.frame_count] = state @@ -538,104 +116,6 @@ class Recording:          frame_id = self.states.index(thing)          self.step(first_frame=frame_id, replay=True) -class Registers: -    order = [ -        "pc", -        "sp", -        "af", -        "bc", -        "de", -        "hl", -        "iff", -        "div", -        "tima", -        "tma", -        "tac", -        "if", -        "lcdc", -        "stat", -        "scy", -        "scx", -        "ly", -        "lyc", -        "dma", -        "wy", -        "wx", -        "vbk", -        "hdma1", -        "hdma2", -        "hdma3", -        "hdma4", -        "hdma5", -        "svbk", -        "ie", -    ] - -    def __setitem__(self, key, value): -        current_registers = get_registers() -        current_registers[Registers.order.index(key)] = value -        set_registers(current_registers) - -    def __getitem__(self, key): -        current_registers = get_registers() -        return current_registers[Registers.order.index(key)] - -    def __list__(self): -        return get_registers() - -    def _get_register(id): -        def constructed_func(self, id=copy(id)): -            return get_registers()[id] -        return constructed_func - -    def _set_register(id): -        def constructed_func(self, value, id=copy(id)): -            current_registers = get_registers() -            current_registers[id] = value -            set_registers(current_registers) -        return constructed_func - -    pc = property(fget=_get_register(0), fset=_set_register(0)) -    sp = property(fget=_get_register(1), fset=_set_register(1)) -    af = property(fget=_get_register(2), fset=_set_register(2)) -    bc = property(fget=_get_register(3), fset=_set_register(3)) -    de = property(fget=_get_register(4), fset=_set_register(4)) -    hl = property(fget=_get_register(5), fset=_set_register(5)) -    iff = property(fget=_get_register(6), fset=_set_register(6)) -    div = property(fget=_get_register(7), fset=_set_register(7)) -    tima = property(fget=_get_register(8), fset=_set_register(8)) -    tma = property(fget=_get_register(9), fset=_set_register(9)) -    tac = property(fget=_get_register(10), fset=_set_register(10)) -    _if = property(fget=_get_register(11), fset=_set_register(11)) -    lcdc = property(fget=_get_register(12), fset=_set_register(12)) -    stat = property(fget=_get_register(13), fset=_set_register(13)) -    scy = property(fget=_get_register(14), fset=_set_register(14)) -    scx = property(fget=_get_register(15), fset=_set_register(15)) -    ly = property(fget=_get_register(16), fset=_set_register(16)) -    lyc = property(fget=_get_register(17), fset=_set_register(17)) -    dma = property(fget=_get_register(18), fset=_set_register(18)) -    wy = property(fget=_get_register(19), fset=_set_register(19)) -    wx = property(fget=_get_register(20), fset=_set_register(20)) -    vbk = property(fget=_get_register(21), fset=_set_register(21)) -    hdma1 = property(fget=_get_register(22), fset=_set_register(22)) -    hdma2 = property(fget=_get_register(23), fset=_set_register(23)) -    hdma3 = property(fget=_get_register(24), fset=_set_register(24)) -    hdma4 = property(fget=_get_register(25), fset=_set_register(25)) -    hdma5 = property(fget=_get_register(26), fset=_set_register(26)) -    svbk = property(fget=_get_register(27), fset=_set_register(27)) -    ie = property(fget=_get_register(28), fset=_set_register(28)) - -    def __repr__(self): -        spacing = "\t" -        output = "Registers:\n" -        for (id, each) in enumerate(self.order): -            output += spacing + each + " = " + hex(get_registers()[id]) -            #hex(self[each]) -            output += "\n" -        return output - -registers = Registers() -  def call(bank, address):      """      Jumps into a function at a certain address. @@ -668,66 +148,6 @@ def call(bank, address):      else:          registers["pc"] = address -class cheats: -    """ -    Helpers to manage the cheating infrastructure. - -    import vba; vba.load_rom(); vba.cheats.add_gameshark("0100CFCF", "text speedup 1"); vba.cheats.add_gameshark("0101CCCF", "text speedup 2"); vba.go() -    """ - -    @staticmethod -    def enable(id): -        """ -        void gbCheatEnable(int i) -        """ -        Gb.cheatEnable(id) - -    @staticmethod -    def disable(id): -        """ -        void gbCheatDisable(int i) -        """ -        Gb.cheatDisable(id) - -    @staticmethod -    def load_file(filename): -        """ -        Loads a .clt file. By default each cheat is disabled. -        """ -        Gb.loadCheatsFromFile(filename) - -    @staticmethod -    def remove_all(): -        """ -        Removes all cheats from memory. - -        void gbCheatRemoveAll() -        """ -        Gb.cheatRemoveAll() - -    @staticmethod -    def remove_cheat(id): -        """ -        Removes a specific cheat from memory by id. - -        void gbCheatRemove(int i) -        """ -        Gb.cheatRemove(id) - -    @staticmethod -    def add_gamegenie(code, description=""): -        """ -        void gbAddGgCheat(const char *code, const char *desc) -        """ -        Gb.cheatAddGamegenie(code, description) - -    @staticmethod -    def add_gameshark(code, description=""): -        """ -        gbAddGsCheat(const char *code, const char *desc) -        """ -        Gb.cheatAddGameshark(code, description) -  def get_stack():      """      Return a list of functions on the stack. @@ -1133,19 +553,6 @@ class crystal:              memory = get_memory()  class TestEmulator(unittest.TestCase): -    try: -        state = load_state("cheating-12") -    except: -        if "__name__" == "__main__": -            raise Exception("failed to setup unit tests because no save state found") - -    def setUp(self): -        load_rom() -        set_state(self.state) - -    def tearDown(self): -        shutdown() -      def test_PlaceString(self):          call(0, 0x1078) | 
