shithub: pokecrystal

Download patch

ref: bcd9794cb5025bb594770a503e59c5b3c8577269
parent: 2a22a91cbb639c2eeb2644e40234bcf8a18eca4b
author: Bryan Bishop <[email protected]>
date: Mon Mar 26 22:01:04 EDT 2012

more command classes

--- a/extras/crystal.py
+++ b/extras/crystal.py
@@ -3,6 +3,7 @@
 import sys, os, inspect, md5, json
 from copy import copy, deepcopy
 import subprocess
+from new import classobj
 
 #for IntervalMap
 from bisect import bisect_left, bisect_right
@@ -2055,100 +2056,6 @@
     0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
 ]
 
-class Command():
-    def __init__(self, address=None):
-        raise Exception, "i don't think anything actually calls this?"
-        self.params = {}
-        if not is_valid_address(address):
-            raise Exception, "address is invalid"
-        self.address = address
-    def to_asm(self):
-        #start with the rgbasm macro name for this command
-        output = self.macro_name
-        #return if there are no params
-        if len(self.param_types.keys()) == 0: return output
-        #first one will have no prefixing comma
-        first = True
-        #start reading the bytes after the command byte
-        current_address = self.address+1
-        #add each param
-        for param in self.params:
-            name = param.name
-            #the first param shouldn't have ", " prefixed
-            if first: first = False
-            #but all other params should
-            else: output += ", "
-            #now add the asm-compatible param string
-            output += obj.to_asm()
-            current_address += obj.size
-        #for param_type in self.param_types:
-        #    name = param_type["name"]
-        #    klass = param_type["klass"]
-        #    #create an instance of this type
-        #    #tell it to begin parsing at this latest byte
-        #    obj = klass(address=current_address)
-        #    #the first param shouldn't have ", " prefixed
-        #    if first: first = False
-        #    #but all other params should
-        #    else: output += ", "
-        #    #now add the asm-compatible param string
-        #    output += obj.to_asm()
-        #    current_address += obj.size
-        return output
-    def parse(self):
-        #id, size (inclusive), param_types
-        #param_type = {"name": each[1], "class": each[0]}
-        self.params = {}
-        current_address = self.address+1
-        byte = int(rom[self.address])
-        if not byte == self.id:
-            raise Exception, "this should never happen"
-        i = 0
-        for (key, param_type) in self.param_types.items():
-            name = param_type["name"]
-            klass = param_type["class"]
-            #make an instance of this class, like SingleByteParam()
-            #or ItemLabelByte.. by making an instance, obj.parse() is called
-            obj = klass(address=current_address, name=name)
-            #save this for later
-            self.params[i] = obj
-            #increment our counters
-            current_address += obj.size
-            i += 1
-        return True
-class GivePoke(Command):
-    id = 0x2D
-    size = 4 #minimum
-    param_types = {
-                  0: {"name": "pokemon", "class": PokemonParam},
-                  1: {"name": "level", "class": SingleByteParam},
-                  2: {"name": "item", "class": ItemLabelByte},
-                  3: {"name": "trainer", "class": SingleByteParam},
-                  4: {"name": "trainer_name_pointer", "class": MultiByteParam}, #should probably use TextLabelParam
-                  5: {"name": "pkmn_nickname", "class": MultiByteParam}, #XXX TextLabelParam ?
-                  ]
-    def parse(self):
-        self.params = {}
-        byte = int(rom[self.address])
-        if not byte == self.id:
-            raise Exception, "this should never happen"
-        current_address = self.address+1
-        i = 0
-        for (key, param_type) in self.param_types.items():
-            #stop executing after the 4th byte unless it == 0x1
-            if i == 4 and self.params[-1].byte != 1: break
-            name = param_type["name"]
-            klass = param_type["class"]
-            #make an instance of this class, like SingleByteParam()
-            #or ItemLabelByte.. by making an instance, obj.parse() is called
-            obj = klass(address=current_address, name=name)
-            #save this for later
-            self.params[i] = obj
-            #increment our counters
-            current_address += obj.size
-            i += 1
-        return True
-
 class SingleByteParam():
     """or SingleByte(CommandParam)"""
     size = 1
@@ -2158,7 +2065,7 @@
             setattr(self, key, value)
         #check address
         if not hasattr(self, "address"):
-            raise Exception, "an address is a requirement")
+            raise Exception, "an address is a requirement"
         elif self.address == None:
             raise Exception, "address must not be None"
         elif not is_valid_address(self.address):
@@ -2182,7 +2089,7 @@
         label = find_item_label_by_id(self.byte)
         if label: return label
         elif not label: return DollarSignByte.to_asm(self)
-class DecimalByte(SingleByteParam):
+class DecimalParam(SingleByteParam):
     should_be_decimal = True
 
 class MultiByteParam():
@@ -2195,7 +2102,7 @@
             setattr(self, key, value)
         #check address
         if not hasattr(self, "address") or self.address == None:
-            raise Exception, "an address is a requirement")
+            raise Exception, "an address is a requirement"
         elif not is_valid_address(self.address):
             raise Exception, "address must be valid"
         #check size
@@ -2273,7 +2180,7 @@
     PointerLabelParam.parse(self)
     address = calculate_pointer_from_bytes_at(self.address, bank=self.bank)
     self.script = parse_script_engine_script_at(address)
-ScriptPointerLabelParam = _parse_script_pointer_bytes
+ScriptPointerLabelParam.parse = _parse_script_pointer_bytes
 ScriptPointerLabelBeforeBank.parse = _parse_script_pointer_bytes
 ScriptPointerLabelAfterBank.parse = _parse_script_pointer_bytes
 class PointerLabelToScriptPointer(PointerLabelParam):
@@ -2340,16 +2247,31 @@
         if pokemon_constant: return pokemon_constant
         else: return str(self.byte)
 class PointerParamToItemAndLetter(MultiByteParam):
-    raise NotImplementedError, bryan_message
     #[2F][2byte pointer to item no + 0x20 bytes letter text]
+    #raise NotImplementedError, bryan_message
+    pass
 class TrainerIdParam(SingleByteParam):
-    raise NotImplementedError, bryan_message
+    #raise NotImplementedError, bryan_message
+    pass
 class TrainerGroupParam(SingleByteParam):
-    raise NotImplementedError, bryan_message
+    #raise NotImplementedError, bryan_message
+    pass
+class MenuDataPointerParam(PointerLabelParam):
+    #read menu data at the target site
+    #raise NotImplementedError, bryan_message
+    pass
+class RawTextPointerLabelParam(PointerLabelParam):
+    #is this to raw text? or to a text script?
+    #raise NotImplementedError, bryan_message
+    pass
+class TextPointerLabelParam(PointerLabelParam):
+    #definitely points to a text script
+    pass
+class MovementPointerLabelParam(PointerLabelParam):
+    pass
+class MapDataPointerParam(PointerLabelParam):
+    pass
 
-SingleByteParam, HexByte, DollarSignByte, ItemLabelByte
-PointerLabelParam, PointerLabelBeforeBank, PointerLabelAfterBank
-
 #byte: [name, [param1 name, param1 type], [param2 name, param2 type], ...]
 #0x9E: ["verbosegiveitem", ["item", ItemLabelByte], ["quantity", SingleByteParam]],
 pksv_crystal_more = {
@@ -2400,7 +2322,7 @@
     0x2B: ["checktime", ["time", SingleByteParam]],
     0x2C: ["checkpoke", ["pkmn", PokemonParam]],
 #0x2D: ["givepoke", ], .... see GivePoke class
-    0x2E: ["giveegg", ["pkmn", PokemonParam], ["level", DecimalByte]],
+    0x2E: ["giveegg", ["pkmn", PokemonParam], ["level", DecimalParam]],
     0x2F: ["givepokeitem", ["pointer", PointerParamToItemAndLetter]],
     0x30: ["checkpokeitem", ["pointer", PointerParamToItemAndLetter]], #not pksv
     0x31: ["checkbit1", ["bit_number", SingleByteParam]],
@@ -2422,94 +2344,207 @@
     0x41: ["itemtotext", ["item", ItemLabelByte], ["memory", SingleByteParam]],
     0x42: ["mapnametotext", ["memory", SingleByteParam]], #not pksv
     0x43: ["trainertotext", ["trainer_id", TrainerIdParam], ["trainer_group", TrainerGroupParam], ["memory", SingleByteParam]],
-    0x44: ["stringtotext", ],
-    0x45: ["itemnotify", ],
-    0x46: ["pocketisfull", ],
-    0x47: ["loadfont", ],
-    0x48: ["refreshscreen", ],
-    0x49: ["loadmovesprites", ],
-    0x4B: ["3writetext", ],
-    0x4C: ["2writetext", ],
-    0x4E: ["yesorno", ],
-    0x4F: ["loadmenudata", ],
-    0x50: ["writebackup", ],
-    0x51: ["jumptextfaceplayer", ],
-    0x53: ["jumptext", ],
-    0x54: ["closetext", ],
-    0x55: ["keeptextopen", ],
-    0x56: ["pokepic", ],
-    0x57: ["pokepicyesorno", ],
-    0x58: ["interpretmenu", ],
-    0x59: ["interpretmenu2", ],
-    0x5D: ["loadpokedata", ],
-    0x5E: ["loadtrainer", ],
-    0x5F: ["startbattle", ],
-    0x60: ["returnafterbattle", ],
-    0x61: ["catchtutorial", ],
-    0x64: ["winlosstext", ],
-    0x66: ["talkaftercancel", ],
-    0x68: ["setlasttalked", ],
-    0x69: ["applymovement", ],
-    0x6B: ["faceplayer", ],
-    0x6C: ["faceperson", ],
-    0x6D: ["variablesprite", ],
-    0x6E: ["disappear", ],
-    0x6F: ["appear", ],
-    0x70: ["follow", ],
-    0x71: ["stopfollow", ],
-    0x72: ["moveperson", ],
-    0x75: ["showemote", ],
-    0x76: ["spriteface", ],
-    0x77: ["follownotexact", ],
-    0x78: ["earthquake", ],
-    0x7A: ["changeblock", ],
-    0x7B: ["reloadmap", ],
-    0x7C: ["reloadmappart", ],
-    0x7D: ["writecmdqueue", ],
-    0x7E: ["delcmdqueue", ],
-    0x7F: ["playmusic", ],
-    0x80: ["playrammusic", ],
-    0x81: ["musicfadeout", ],
-    0x82: ["playmapmusic", ],
-    0x83: ["reloadmapmusic", ],
-    0x84: ["cry", ],
-    0x85: ["playsound", ],
-    0x86: ["waitbutton", ],
-    0x87: ["warpsound", ],
-    0x88: ["specialsound", ],
-    0x89: ["passtoengine", ],
-    0x8A: ["newloadmap", ],
-    0x8B: ["pause", ],
-    0x8C: ["deactivatefacing", ],
-    0x8D: ["priorityjump", ],
-    0x8E: ["warpcheck", ],
-    0x8F: ["ptpriorityjump", ],
-    0x90: ["return", ],
-    0x91: ["end", ],
-    0x92: ["reloadandreturn", ],
-    0x93: ["resetfuncs", ],
-    0x94: ["pokemart", ],
-    0x95: ["elevator", ],
-    0x96: ["trade", ],
-    0x97: ["askforphonenumber", ],
-    0x98: ["phonecall", ],
-    0x99: ["hangup", ],
-    0x9A: ["describedecoration", ],
-    0x9B: ["fruittree", ],
-    0x9C: ["specialphonecall", ],
-    0x9D: ["checkphonecall", ],
-    0x9E: ["verbosegiveitem", ],
-    0xA0: ["loadwilddata", ],
-    0xA1: ["halloffame", ],
-    0xA2: ["credits", ],
-    0xA3: ["warpfacing", ],
-    0xA4: ["storetext", ],
-    0xA5: ["displaylocation", ],
+    0x44: ["stringtotext", ["text_pointer", RawTextPointerLabelParam], ["memory", SingleByteParam]],
+    0x45: ["itemnotify"],
+    0x46: ["pocketisfull"],
+    0x47: ["loadfont"],
+    0x48: ["refreshscreen", ["dummy", SingleByteParam]],
+    0x49: ["loadmovesprites"],
+    0x4A: ["loadbytec1ce", ["byte", SingleByteParam]], #not pksv
+    0x4B: ["3writetext", ["text_pointer", PointerLabelBeforeBank]],
+    0x4C: ["2writetext", ["text_pointer", RawTextPointerLabelParam]], #XXX - is this to a text script, or raw text?
+    0x4D: ["repeattext", ["byte", SingleByteParam], ["byte", SingleByteParam]], #not pksv
+    0x4E: ["yesorno"],
+    0x4F: ["loadmenudata", ["data", MenuDataPointerParam]],
+    0x50: ["writebackup"],
+#XXX test123
+    0x51: ["jumptextfaceplayer", ["text_pointer", RawTextPointerLabelParam]],
+    0x53: ["jumptext", ["text_pointer", TextPointerLabelParam]],
+    0x54: ["closetext"],
+    0x55: ["keeptextopen"],
+    0x56: ["pokepic", ["pokemon", PokemonParam]],
+    0x57: ["pokepicyesorno"],
+    0x58: ["interpretmenu"],
+    0x59: ["interpretmenu2"],
+#not pksv
+    0x5A: ["loadpikachudata"],
+    0x5B: ["battlecheck"],
+    0x5C: ["loadtrainerdata"],
+#back to pksv..
+    0x5D: ["loadpokedata", ["pokemon", PokemonParam], ["level", DecimalParam]],
+    0x5E: ["loadtrainer", ["trainer_group", TrainerGroupParam], ["trainer_id", TrainerIdParam]],
+    0x5F: ["startbattle"],
+    0x60: ["returnafterbattle"],
+    0x61: ["catchtutorial", ["byte", SingleByteParam]],
+#not pksv
+    0x62: ["trainertext", ["which_text", SingleByteParam]],
+    0x63: ["trainerstatus", ["action", SingleByteParam]],
+#back to pksv..
+    0x64: ["winlosstext", ["win_text_pointer", TextPointerLabelParam], ["loss_text_pointer", TextPointerLabelParam]],
+    0x65: ["scripttalkafter"], #not pksv
+    0x66: ["talkaftercancel"],
+    0x67: ["istalkafterscriptexecutedafterbattle"], #not pksv
+    0x68: ["setlasttalked", ["person", SingleByteParam]],
+    0x69: ["applymovement", ["person", SingleByteParam], ["data", MovementPointerLabelParam]],
+    0x6A: ["applymovement2", ["data", MovementPointerLabelParam]], #not pksv
+    0x6B: ["faceplayer"],
+    0x6C: ["faceperson", ["person1", SingleByteParam], ["person2", SingleByteParam]],
+    0x6D: ["variablesprite", ["byte", SingleByteParam], ["sprite", SingleByteParam]],
+    0x6E: ["disappear", ["person", SingleByteParam]], #hideperson
+    0x6F: ["appear", ["person", SingleByteParam]], #showperson
+    0x70: ["follow", ["person2", SingleByteParam], ["person1", SingleByteParam]], 
+    0x71: ["stopfollow"],
+    0x72: ["moveperson", ["person", SingleByteParam], ["x", SingleByteParam], ["y", SingleByteParam]],
+    0x73: ["writepersonxy", ["person", SingleByteParam]], #not pksv
+    0x74: ["loademote", ["bubble", SingleByteParam]],
+    0x75: ["showemote", ["bubble", SingleByteParam], ["person", SingleByteParam], ["time", SingleByteParam]],
+    0x76: ["spriteface", ["person", SingleByteParam], ["facing", SingleByteParam]],
+    0x77: ["follownotexact", ["person2", SingleByteParam], ["person1", SingleByteParam]],
+    0x78: ["earthquake", ["param", SingleByteParam]],
+    0x79: ["changemap", ["map_data_pointer", MapDataPointerParam]],
+    0x7A: ["changeblock", ["x", SingleByteParam], ["y", SingleByteParam], ["block", SingleByteParam]],
+    0x7B: ["reloadmap"],
+    0x7C: ["reloadmappart"],
+    0x7D: ["writecmdqueue", ["queue_pointer", MultiByteParam]],
+    0x7E: ["delcmdqueue", ["byte", SingleByteParam]],
+    0x7F: ["playmusic", ["music_pointer", MultiByteParam]],
+    0x80: ["playrammusic"],
+    0x81: ["musicfadeout", ["music", MultiByteParam], ["fadetime", SingleByteParam]],
+    0x82: ["playmapmusic"],
+    0x83: ["reloadmapmusic"],
+    0x84: ["cry", ["cry_id", SingleByteParam], ["wtf", SingleByteParam]], #XXX maybe it should use PokemonParam
+    0x85: ["playsound", ["sound_pointer", MultiByteParam]],
+    0x86: ["waitbutton"],
+    0x87: ["warpsound"],
+    0x88: ["specialsound"],
+    0x89: ["passtoengine", ["data_pointer", PointerLabelBeforeBank]],
+    0x8A: ["newloadmap", ["which_method", SingleByteParam]],
+    0x8B: ["pause", ["length", SingleByteParam]],
+    0x8C: ["deactivatefacing", ["time", SingleByteParam]],
+    0x8D: ["priorityjump", ["pointer", ScriptPointerLabelParam]],
+    0x8E: ["warpcheck"],
+    0x8F: ["ptpriorityjump", ["pointer", ScriptPointerLabelParam]],
+    0x90: ["return"],
+    0x91: ["end"],
+    0x92: ["reloadandreturn"],
+    0x93: ["resetfuncs"],
+    0x94: ["pokemart", ["dialog_id", SingleByteParam], ["mart_id", SingleByteParam]],
+    0x95: ["elevator", ["floor_list_pointer", PointerLabelParam]],
+    0x96: ["trade", ["trade_id", SingleByteParam]],
+    0x97: ["askforphonenumber", ["number", SingleByteParam]],
+    0x98: ["phonecall", ["caller_name", RawTextPointerLabelParam]],
+    0x99: ["hangup"],
+    0x9A: ["describedecoration", ["byte", SingleByteParam]],
+    0x9B: ["fruittree", ["tree_id", SingleByteParam]],
+    0x9C: ["specialphonecall", ["call_id", SingleByteParam], ["wtf", SingleByteParam]],
+    0x9D: ["checkphonecall"],
+    0x9E: ["verbosegiveitem", ["item", ItemLabelByte], ["quantity", DecimalParam]],
+    0xA0: ["loadwilddata", ["map_group", MapGroupParam], ["map_id", MapIdParam]],
+    0xA1: ["halloffame"],
+    0xA2: ["credits"],
+    0xA3: ["warpfacing", ["facing", SingleByteParam], ["map_group", MapGroupParam], ["map_id", MapIdParam], ["x", SingleByteParam], ["y", SingleByteParam]],
+    0xA4: ["storetext", ["pointer", PointerLabelBeforeBank], ["memory", SingleByteParam]],
+    0xA5: ["displaylocation", ["id", SingleByteParam]],
 }
+
+class Command():
+    def __init__(self, address=None):
+        raise Exception, "i don't think anything actually calls this?"
+        self.params = {}
+        if not is_valid_address(address):
+            raise Exception, "address is invalid"
+        self.address = address
+    def to_asm(self):
+        #start with the rgbasm macro name for this command
+        output = self.macro_name
+        #return if there are no params
+        if len(self.param_types.keys()) == 0: return output
+        #first one will have no prefixing comma
+        first = True
+        #start reading the bytes after the command byte
+        current_address = self.address+1
+        #add each param
+        for param in self.params:
+            name = param.name
+            #the first param shouldn't have ", " prefixed
+            if first: first = False
+            #but all other params should
+            else: output += ", "
+            #now add the asm-compatible param string
+            output += obj.to_asm()
+            current_address += obj.size
+        #for param_type in self.param_types:
+        #    name = param_type["name"]
+        #    klass = param_type["klass"]
+        #    #create an instance of this type
+        #    #tell it to begin parsing at this latest byte
+        #    obj = klass(address=current_address)
+        #    #the first param shouldn't have ", " prefixed
+        #    if first: first = False
+        #    #but all other params should
+        #    else: output += ", "
+        #    #now add the asm-compatible param string
+        #    output += obj.to_asm()
+        #    current_address += obj.size
+        return output
+    def parse(self):
+        #id, size (inclusive), param_types
+        #param_type = {"name": each[1], "class": each[0]}
+        self.params = {}
+        current_address = self.address+1
+        byte = int(rom[self.address])
+        if not byte == self.id:
+            raise Exception, "this should never happen"
+        i = 0
+        for (key, param_type) in self.param_types.items():
+            name = param_type["name"]
+            klass = param_type["class"]
+            #make an instance of this class, like SingleByteParam()
+            #or ItemLabelByte.. by making an instance, obj.parse() is called
+            obj = klass(address=current_address, name=name)
+            #save this for later
+            self.params[i] = obj
+            #increment our counters
+            current_address += obj.size
+            i += 1
+        return True
+class GivePoke(Command):
+    id = 0x2D
+    size = 4 #minimum
+    param_types = {
+                  0: {"name": "pokemon", "class": PokemonParam},
+                  1: {"name": "level", "class": SingleByteParam},
+                  2: {"name": "item", "class": ItemLabelByte},
+                  3: {"name": "trainer", "class": SingleByteParam},
+                  4: {"name": "trainer_name_pointer", "class": MultiByteParam}, #should probably use TextLabelParam
+                  5: {"name": "pkmn_nickname", "class": MultiByteParam}, #XXX TextLabelParam ?
+                  }
+    def parse(self):
+        self.params = {}
+        byte = int(rom[self.address])
+        if not byte == self.id:
+            raise Exception, "this should never happen"
+        current_address = self.address+1
+        i = 0
+        for (key, param_type) in self.param_types.items():
+            #stop executing after the 4th byte unless it == 0x1
+            if i == 4 and self.params[-1].byte != 1: break
+            name = param_type["name"]
+            klass = param_type["class"]
+            #make an instance of this class, like SingleByteParam()
+            #or ItemLabelByte.. by making an instance, obj.parse() is called
+            obj = klass(address=current_address, name=name)
+            #save this for later
+            self.params[i] = obj
+            #increment our counters
+            current_address += obj.size
+            i += 1
+        return True
+
 #these cause the script to end; used in create_command_classes
 pksv_crystal_more_enders = [0x03, 0x04, 0x05, 0x0C, 0x51, 0x53,
                             0x8D, 0x8F, 0x90, 0x91, 0x92, 0x9B] 
-def create_command_classes():
+def create_command_classes(debug=False):
     """creates some classes for each command byte"""
     klasses = []
     for (byte, cmd) in pksv_crystal_more.items():
@@ -2521,14 +2556,17 @@
             for (i, each) in enumerate(param_types):
                 thing = {"name": each[0], "class": each[1]}
                 params["param_types"][i] = thing
+                if debug:
+                    print "each is: " + str(each)
+                    print "thing[class] is: " + str(thing["class"])
                 params["size"] += thing["class"].size
         klass_name = cmd_name+"Command"
         klass = classobj(klass_name, (Command,), params)
         globals()[klass_name] = klass
-        klasses = append(klass)
+        klasses.append(klass)
     #later an individual klass will be instantiated to handle something
     return klasses
-create_command_classes()
+command_classes = create_command_classes()
 
 #use this to keep track of commands without pksv names
 pksv_no_names = {}