diff options
author | Bryan Bishop <kanzure@gmail.com> | 2013-11-10 15:04:31 -0600 |
---|---|---|
committer | Bryan Bishop <kanzure@gmail.com> | 2013-11-10 15:04:31 -0600 |
commit | cab54cc723ee66f962d36d2e7c6d844a3df9b3b0 (patch) | |
tree | 62896eac3048ac086b02d9ba6e91e82b68d7f089 | |
parent | 8b637503a560c7028ac066d50b7aa3923e49082a (diff) |
crude attempt at injecting asm into wram
-rw-r--r-- | pokemontools/vba/vba.py | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/pokemontools/vba/vba.py b/pokemontools/vba/vba.py index 2a2c4ca..bd737da 100644 --- a/pokemontools/vba/vba.py +++ b/pokemontools/vba/vba.py @@ -187,6 +187,73 @@ class crystal(object): return addresses + def inject_asm(self, asm, address=0xc6d4): + """ + Writes asm to memory. Makes the emulator run the asm. + + This function will append "ret" to the list of bytes. Before returning, + it updates the value at the first byte to indicate that the function + has executed. + + The first byte at the given address is reserved for whether the asm has + finished executing. + """ + memory = self.vba.memory + + # the first byte is reserved for whether the script has finished + has_finished = address + memory[has_finished] = 0 + + # the second byte is where the script will be stored + script_address = address + 1 + + # TODO: error checking; make sure the last byte doesn't already return. + # Use some functions from gbz80disasm to perform this check. + + # set a value to indicate that the script has executed + set_has_finished = [ + # push af + 0xf5, + + # ld a, 1 + 0xfa, 1, + + # ld [has_finished], a + 0x77, has_finished & 0xff, has_finished >> 8, + + # pop af + 0xf1, + + # ret + 0xc9, + ] + + # append the last opcodes to the script + asm.extend(set_has_finished) + + memory[script_address : script_address + len(asm)] = asm + self.vba.memory = memory + + # make the emulator call the script + self.call(script_address, bank=0) + + # make the emulator step forward + self.vba.step(count=1) + + # check if the script has executed + # TODO: should this raise an exception if the script didn't finish? + if self.vba.memory[has_finished] == 0: + return False + elif self.vba.memory[has_finished] == 1: + return True + else: + raise Exception( + "has_finished at {has_finished} was overwritten with an unexpected value {value}".format( + has_finished=hex(has_finished), + value=self.vba.memory[has_finished], + ) + ) + def text_wait(self, step_size=1, max_wait=200, sfx_limit=0, debug=False, callback=None): """ Presses the "A" button when text is done being drawn to screen. |