shithub: pokecrystal

Download patch

ref: 2588ff6255542bcaf8f20a6cafa3e9943cd0d292
parent: c42b254081033bbb54ba56cb96ead7439d8452c8
author: Bryan Bishop <[email protected]>
date: Sat Apr 21 14:09:03 EDT 2012

insertion of asm dependencies

--- a/extras/crystal.py
+++ b/extras/crystal.py
@@ -708,7 +708,9 @@
         #    sys.exit()
 
         self.commands = commands
+        self.last_address = offset - 1 #why -1??
         script_parse_table[original_address:offset-1] = self
+        self.size = self.byte_count = self.last_address - original_address
         return commands
 
     def get_dependencies(self):
@@ -910,8 +912,8 @@
         if len(output)!=0 and output[-1] == "\n":
             include_newline = ""
         output += include_newline + "; " + hex(start_address) + " + " + str(byte_count) + " bytes = " + hex(start_address + byte_count)
-        print output
-        return (output, byte_count)
+        self.size = self.byte_count = byte_count
+        return output
 
 def parse_text_engine_script_at(address, map_group=None, map_id=None, debug=True, show=True, force=False):
     """parses a text-engine script ("in-text scripts")
@@ -1516,7 +1518,8 @@
         for (key, param) in self.params.items():
             if hasattr(param, "get_dependencies"):
                 deps = param.get_dependencies()
-                dependencies.extend(deps)
+                if deps != None:
+                    dependencies.extend(deps)
         return dependencies
 
     def to_asm(self):
@@ -2113,7 +2116,7 @@
     def get_dependencies(self):
         dependencies = []
         thing = script_parse_table[self.params[4].parsed_address]
-        if thing:
+        if thing and thing != self.params[4]:
             dependencies.append(thing)
         return dependencies
 
@@ -3411,7 +3414,8 @@
         output += "db %d\n"%self.trigger_count
         if len(self.triggers) > 0:
             output += "\n; triggers\n"
-            output += "\n".join(["dw "+p.to_asm() for p in self.triggers]) + "\n"
+            output += "\n".join([str("dw "+p.to_asm()) for p in self.triggers])
+            output += "\n"
         output += "\n; callback count\n"
         output += "db %d"%self.callback_count
         if len(self.callbacks) > 0:
@@ -4203,7 +4207,11 @@
     #create a line like "label: ; 0x10101"
     asm = some_object.label + ": ; " + hex(some_object.address) + "\n"
     #now add the inner/actual asm
-    asm += spacing + some_object.to_asm().replace("\n", "\n"+spacing).replace("\n"+spacing+"\n"+spacing, "\n\n"+spacing)
+    #asm += spacing + some_object.to_asm().replace("\n", "\n"+spacing).replace("\n"+spacing+"\n"+spacing, "\n\n"+spacing)
+    asmr = some_object.to_asm()
+    asmr = asmr.replace("\n", "\n"+spacing)
+    asmr = asmr.replace("\n"+spacing+"\n", "\n\n"+spacing)
+    asm += spacing + asmr
     #show the address of the next byte below this
     asm += "\n; " + hex(last_address)
     return asm
@@ -4437,16 +4445,26 @@
         return self.line
 
 class Incbin:
-    def __init__(self, line, bank=None):
+    def __init__(self, line, bank=None, debug=False):
         self.line = line
         self.bank = bank
         self.replace_me = False
+        self.debug = debug
         self.parse()
     def parse(self):
         incbin = self.line
         partial_start = incbin[21:]
         start = partial_start.split(",")[0].replace("$", "0x")
-        start = eval(start)
+
+        if self.debug:
+            print "Incbin.parse -- line is: " + self.line
+            print "Incbin.parse -- partial_start is: " + partial_start
+            print "Incbin.parse -- start is: " + start
+        try:
+            start = eval(start)
+        except Exception, e:
+            raise Exception, "problem with evaluating interval range"
+
         start_hex = hex(start).replace("0x", "$")
 
         partial_interval = incbin[21:].split(",")[1]
@@ -4473,10 +4491,15 @@
             raise Exception, "this incbin doesn't handle this address"
         incbins = []
 
+        if self.debug:
+            print "splitting an incbin ("+self.line+") into three at "+hex(start_address)+" for "+str(byte_count)+" bytes"
+
         #start, end1, end2 (to be printed as start, end1 - end2)
-        if (start_address - self.start) > 0:
-            first = (self.start, start_address, self.start)
+        if (start_address - self.start_address) > 0:
+            first = (self.start_address, start_address, self.start_address)
             incbins.append(Incbin("INCBIN \"baserom.gbc\",$%.2x,$%.2x - $%.2x" % (first[0], first[1], first[2])))
+            if self.debug:
+                print "    " + incbins[0].line
         else:
             #skip this one because we're not including anything
             first = None
@@ -4485,10 +4508,14 @@
         second = (start_address, byte_count)
         incbins.append(Incbin("INCBIN \"baserom.gbc\",$%.2x,$%.2x" % (start_address, byte_count)))
         incbins[-1].replace_me = True
+        if self.debug:
+            print "    " + incbins[-1].line
 
-        if (end - (start_address + byte_count)) > 0:
-            third = (start_address + byte_count, end - (start_address + byte_count))
+        if (self.last_address - (start_address + byte_count)) > 0:
+            third = (start_address + byte_count, self.last_address - (start_address + byte_count))
             incbins.append(Incbin("INCBIN \"baserom.gbc\",$%.2x,$%.2x" % (third[0], third[1])))
+            if self.debug:
+                print "    " + incbins[-1].line
 
         return incbins
         
@@ -4503,6 +4530,10 @@
         self.bank_id  = bank_id
         start_address = bank_id * 0x4000
         end_address   = (bank_id * 0x4000) + 0x4000 - 1
+        
+        self.address = self.start_address = start_address
+        self.last_address = None
+        self.end_address = None
         #this entity doesn't actually take up this space..
         #although it could be argued that lines should exist under this object
         #self.address  = self.start_address = start_address
@@ -4512,9 +4543,10 @@
 
 class Asm:
     """controls the overall asm output"""
-    def __init__(self, filename="../main.asm"):
+    def __init__(self, filename="../main.asm", debug=True):
         self.parts = []
         self.filename = filename
+        self.debug = debug
         self.load_and_parse()
     def load_and_parse(self):
         self.parts = []
@@ -4531,13 +4563,31 @@
                 thing = AsmLine(line, bank=bank)
             self.parts.append(thing)
     def insert(self, new_object):
-        assert hasattr(new_object, "address"), "object needs to have an address property"
-        assert hasattr(new_object, "last_address"), "object needs to have a last address"
+        if isinstance(new_object, TextScript):
+            print "ignoring TextScript object-- these seem very broken?"
+            return
+        if not hasattr(new_object, "address"):
+            print "object needs to have an address property: " + str(new_object)
+            return
+        if not hasattr(new_object, "last_address"):
+            print "object needs to have a last_address property: " + str(new_object)
+            return
         #check if the object is already inserted
         if new_object in self.parts:
-            return "object was previously inserted"
+            print "object was previously inserted ("+str(new_object)+")"
+            return
         start_address = new_object.address
-        end_address = new_object.end_address
+        end_address = new_object.last_address
+        if self.debug:
+            print "object is type="+str(new_object.__class__)+" new_object="+str(new_object)
+            print "start_address="+hex(start_address)+" end_address="+hex(end_address)
+        if (end_address < start_address) or ((end_address - start_address) < 0):
+            if not self.debug:
+                print "object is type="+str(new_object.__class__)+" new_object="+str(new_object)
+                print "start_address="+hex(start_address)+" end_address="+hex(end_address)
+            if hasattr(new_object, "to_asm"):
+                print to_asm(new_object)
+            raise Exception, "Asm.insert was given an object with a bad address range"
         # 1) find which object needs to be replaced
         # or
         # 2) find which object goes after it
@@ -4544,9 +4594,13 @@
         found = False
         for object in list(self.parts):
             #skip objects without a defined interval (like a comment line)
-            if not hasattr(object, "address") and hasattr(object, "last_address"): continue
+            if not hasattr(object, "address") or not hasattr(object, "last_address"):
+                continue
+            #skip an AsmSection
+            if isinstance(object, AsmSection):
+                continue
             #replace an incbin with three incbins, replace middle incbin with whatever
-            if object.address <= start_address <= object.last_address and isinstance(object, Incbin):
+            elif isinstance(object, Incbin) and (object.address <= start_address <= object.last_address):
                 #split up the incbin into three segments
                 incbins = object.split(start_address, end_address - start_address)
                 #figure out which incbin to replace with the new object
@@ -4555,7 +4609,7 @@
                 else: #assume incbins[1].replace_me (the middle one)
                     index = 1
                 #replace that index with the new_object
-                incbins[index] = new_object
+                incbins[index] = to_asm(new_object)
                 #insert these incbins into self.parts
                 gindex = self.parts.index(object)
                 self.parts = self.parts[:gindex] + incbins + self.parts[gindex:]
@@ -4571,6 +4625,17 @@
         if not found:
             raise Exception, "unable to insert object into Asm"
         return True 
+    def insert_single_with_dependencies(self, object):
+        objects = get_dependencies_for(object) + [object]
+        for object in objects:
+            if self.debug:
+                print "object.__class__="+str(object.__class__) + " object is: " + str(object)
+            self.insert(object)
+    def insert_all(self):
+        for each in script_parse_table.items():
+            object = each[1]
+            if type(object) == str: continue
+            self.insert_single_with_dependencies(object)
 
 def index(seq, f):
     """return the index of the first item in seq