shithub: pokecrystal

Download patch

ref: 2b08f91d983063014255cb109509a51c6ad08b3d
parent: cbd8f0925aa7a04969fc1263b23fc246b34879d9
author: Bryan Bishop <[email protected]>
date: Sun Apr 15 10:33:41 EDT 2012

add the old parsers back in for testing

--- a/extras/crystal.py
+++ b/extras/crystal.py
@@ -4812,6 +4812,25 @@
     all_warps.extend(warps)
     return warps
 
+def old_parse_warp_bytes(some_bytes, debug=True):
+    """parse some number of warps from the data"""
+    assert len(some_bytes) % warp_byte_size == 0, "wrong number of bytes"
+    warps = []
+    for bytes in grouper(some_bytes, count=warp_byte_size):
+        y = int(bytes[0], 16)
+        x = int(bytes[1], 16)
+        warp_to = int(bytes[2], 16)
+        map_group = int(bytes[3], 16)
+        map_id = int(bytes[4], 16)
+        warps.append({
+            "y": y,
+            "x": x,
+            "warp_to": warp_to,
+            "map_group": map_group,
+            "map_id": map_id,
+        })
+    return warps
+
 class XYTrigger(Command):
     size = trigger_byte_size
     macro_name = "xy_trigger"
@@ -5048,6 +5067,120 @@
     all_people_events.extend(people_events)
     return people_events
 
+def old_parse_people_event_bytes(some_bytes, address=None, map_group=None, map_id=None, debug=True):
+    """parse some number of people-events from the data
+    see http://hax.iimarck.us/files/scriptingcodes_eng.htm#Scripthdr
+
+    For example, map 1.1 (group 1 map 1) has four person-events.
+   
+        37 05 07 06 00 FF FF 00 00 02 40 FF FF
+        3B 08 0C 05 01 FF FF 00 00 05 40 FF FF
+        3A 07 06 06 00 FF FF A0 00 08 40 FF FF
+        29 05 0B 06 00 FF FF 00 00 0B 40 FF FF
+    """
+    assert len(some_bytes) % people_event_byte_size == 0, "wrong number of bytes"
+
+    #address is not actually required for this function to work...
+    bank = None
+    if address:
+        bank = calculate_bank(address)
+
+    people_events = []
+    for bytes in grouper(some_bytes, count=people_event_byte_size):
+        pict = int(bytes[0], 16)
+        y = int(bytes[1], 16)    #y from top + 4
+        x = int(bytes[2], 16)    #x from left + 4
+        face = int(bytes[3], 16) #0-4 for regular, 6-9 for static facing
+        move = int(bytes[4], 16)
+        clock_time_byte1 = int(bytes[5], 16)
+        clock_time_byte2 = int(bytes[6], 16)
+        color_function_byte = int(bytes[7], 16) #Color|Function
+        trainer_sight_range = int(bytes[8], 16)
+       
+        lower_bits = color_function_byte & 0xF
+        #lower_bits_high = lower_bits >> 2
+        #lower_bits_low = lower_bits & 3
+        higher_bits = color_function_byte >> 4
+        #higher_bits_high = higher_bits >> 2
+        #higher_bits_low = higher_bits & 3
+
+        is_regular_script = lower_bits == 00
+        #pointer points to script
+        is_give_item = lower_bits == 01
+        #pointer points to [Item no.][Amount]
+        is_trainer = lower_bits == 02
+        #pointer points to trainer header
+
+        #goldmap called these next two bytes "text_block" and "text_bank"?
+        script_pointer_byte1 = int(bytes[9], 16)
+        script_pointer_byte2 = int(bytes[10], 16)
+        script_pointer = script_pointer_byte1 + (script_pointer_byte2 << 8)
+        #calculate the full address by assuming it's in the current bank
+        #but what if it's not in the same bank?
+        extra_portion = {}
+        if bank:
+            ptr_address = calculate_pointer(script_pointer, bank)
+            if is_regular_script:
+                print "parsing a person-script at x=" + str(x-4) + " y=" + str(y-4) + " address="+hex(ptr_address)
+                script = parse_script_engine_script_at(ptr_address, map_group=map_group, map_id=map_id)
+                extra_portion = {
+                    "script_address": ptr_address,
+                    "script": script,
+                    "event_type": "script",
+                }
+            if is_give_item:
+                print "... not parsing give item event... [item id][quantity]"
+                extra_portion = {
+                    "event_type": "give_item",
+                    "give_item_data_address": ptr_address,
+                    "item_id": ord(rom[ptr_address]),
+                    "item_qty": ord(rom[ptr_address+1]),
+                }
+            if is_trainer:
+                print "parsing a trainer (person-event) at x=" + str(x) + " y=" + str(y)
+                parsed_trainer = parse_trainer_header_at(ptr_address, map_group=map_group, map_id=map_id)
+                extra_portion = {
+                    "event_type": "trainer",
+                    "trainer_data_address": ptr_address,
+                    "trainer_data": parsed_trainer,
+                }
+        
+        #XXX not sure what's going on here
+        #bit no. of bit table 1 (hidden if set)
+        #note: FFFF for none
+        when_byte = int(bytes[11], 16)
+        hide = int(bytes[12], 16)
+
+        bit_number_of_bit_table1_byte2 = int(bytes[11], 16)
+        bit_number_of_bit_table1_byte1 = int(bytes[12], 16)
+        bit_number_of_bit_table1 = bit_number_of_bit_table1_byte1 + (bit_number_of_bit_table1_byte2 << 8)
+
+        people_event = {
+            "pict": pict,
+            "y": y,                      #y from top + 4
+            "x": x,                      #x from left + 4
+            "face": face,                #0-4 for regular, 6-9 for static facing
+            "move": move,
+            "clock_time": {"1": clock_time_byte1,
+                           "2": clock_time_byte2},       #clock/time setting byte 1
+            "color_function_byte": color_function_byte,  #Color|Function
+            "trainer_sight_range": trainer_sight_range,  #trainer range of sight
+            "script_pointer": {"1": script_pointer_byte1,
+                               "2": script_pointer_byte2},
+
+            #"text_block": text_block,   #script pointer byte 1
+            #"text_bank": text_bank,     #script pointer byte 2
+            "when_byte": when_byte,      #bit no. of bit table 1 (hidden if set)
+            "hide": hide,                #note: FFFF for none
+
+            "is_trainer": is_trainer,
+            "is_regular_script": is_regular_script,
+            "is_give_item": is_give_item,
+        }
+        people_event.update(extra_portion)
+        people_events.append(people_event)
+    return people_events
+
 class SignpostRemoteBase:
     def __init__(self, address, bank=None, map_group=None, map_id=None, signpost=None, debug=False, label=None):
         self.address = address
@@ -5295,6 +5428,65 @@
     all_signposts.extend(signposts)
     return signposts
 
+def old_parse_signpost_bytes(some_bytes, bank=None, map_group=None, map_id=None, debug=True):
+    assert len(some_bytes) % signpost_byte_size == 0, "wrong number of bytes"
+    signposts = []
+    for bytes in grouper(some_bytes, count=signpost_byte_size):
+        y = int(bytes[0], 16)
+        x = int(bytes[1], 16)
+        func = int(bytes[2], 16)
+
+        additional = {}
+        if func in [0, 1, 2, 3, 4]:
+            print "******* parsing signpost script.. signpost is at: x=" + str(x) + " y=" + str(y)
+            script_ptr_byte1 = int(bytes[3], 16)
+            script_ptr_byte2 = int(bytes[4], 16)
+            script_pointer = script_ptr_byte1 + (script_ptr_byte2 << 8)
+       
+            script_address = None
+            script = None
+       
+            script_address = calculate_pointer(script_pointer, bank)
+            script = parse_script_engine_script_at(script_address, map_group=map_group, map_id=map_id)
+
+            additional = {
+            "script_ptr": script_pointer,
+            "script_pointer": {"1": script_ptr_byte1, "2": script_ptr_byte2},
+            "script_address": script_address,
+            "script": script,
+            }
+        elif func in [5, 6]:
+            print "******* parsing signpost script.. signpost is at: x=" + str(x) + " y=" + str(y)
+            ptr_byte1 = int(bytes[3], 16)
+            ptr_byte2 = int(bytes[4], 16)
+            pointer = ptr_byte1 + (ptr_byte2 << 8)
+            address = calculate_pointer(pointer, bank)
+            bit_table_byte1 = ord(rom[address])
+            bit_table_byte2 = ord(rom[address+1])
+            script_ptr_byte1 = ord(rom[address+2])
+            script_ptr_byte2 = ord(rom[address+3])
+            script_address = calculate_pointer_from_bytes_at(address+2, bank=bank)
+            script = parse_script_engine_script_at(script_address, map_group=map_group, map_id=map_id)
+           
+            additional = {
+            "bit_table_bytes": {"1": bit_table_byte1, "2": bit_table_byte2},
+            "script_ptr": script_ptr_byte1 + (script_ptr_byte2 << 8),
+            "script_pointer": {"1": script_ptr_byte1, "2": script_ptr_byte2},
+            "script_address": script_address,
+            "script": script,
+            }
+        else:
+            print ".. type 7 or 8 signpost not parsed yet."
+       
+        spost = {
+            "y": y,
+            "x": x,
+            "func": func,
+        }
+        spost.update(additional)
+        signposts.append(spost)
+    return signposts
+
 class MapHeader:
     base_label = "MapHeader_"
     def __init__(self, address, map_group=None, map_id=None, debug=True, label=None, bank=0x25):
@@ -5338,6 +5530,37 @@
     map_header = MapHeader(address, map_group=map_group, map_id=map_id, debug=debug)
     return map_header
 
+def old_parse_map_header_at(address, map_group=None, map_id=None, debug=True):
+    """parses an arbitrary map header at some address"""
+    print "parsing a map header at: " + hex(address)
+    bytes = rom_interval(address, map_header_byte_size, strings=False, debug=debug)
+    bank = bytes[0]
+    tileset = bytes[1]
+    permission = bytes[2]
+    second_map_header_address = calculate_pointer(bytes[3] + (bytes[4] << 8), 0x25)
+    location_on_world_map = bytes[5] #pokégear world map location
+    music = bytes[6]
+    time_of_day = bytes[7]
+    fishing_group = bytes[8]
+
+    map_header = {
+        "bank": bank,
+        "tileset": tileset,
+        "permission": permission, #map type?
+        "second_map_header_pointer": {"1": bytes[3], "2": bytes[4]},
+        "second_map_header_address": second_map_header_address,
+        "location_on_world_map": location_on_world_map, #area
+        "music": music,
+        "time_of_day": time_of_day,
+        "fishing": fishing_group,
+    }
+    print "second map header address is: " + hex(second_map_header_address)
+    map_header.update(old_parse_second_map_header_at(second_map_header_address, debug=debug))
+    map_header.update(old_parse_map_event_header_at(map_header["event_address"], map_group=map_group, map_id=map_id, debug=debug))
+    #maybe this next one should be under the "scripts" key?
+    map_header.update(old_parse_map_script_header_at(map_header["script_address"], map_group=map_group, map_id=map_id, debug=debug))
+    return map_header
+
 class SecondMapHeader:
     base_label = "SecondMapHeader_"
     def __init__(self, address, map_group=None, map_id=None, debug=True, bank=None, label=None):
@@ -5421,6 +5644,38 @@
     """each map has a second map header"""
     return SecondMapHeader(address, map_group=map_group, map_id=map_id, debug=debug)
 
+def old_parse_second_map_header_at(address, map_group=None, map_id=None, debug=True):
+    """each map has a second map header"""
+    bytes = rom_interval(address, second_map_header_byte_size, strings=False)
+    border_block = bytes[0]
+    height = bytes[1]
+    width = bytes[2]
+    blockdata_bank = bytes[3]
+    blockdata_pointer = bytes[4] + (bytes[5] << 8)
+    blockdata_address = calculate_pointer(blockdata_pointer, blockdata_bank)
+    script_bank = bytes[6]
+    script_pointer = bytes[7] + (bytes[8] << 8)
+    script_address = calculate_pointer(script_pointer, script_bank)
+    event_bank = script_bank
+    event_pointer = bytes[9] + (bytes[10] << 8)
+    event_address = calculate_pointer(event_pointer, event_bank)
+    connections = bytes[11]
+    return {
+        "border_block": border_block,
+        "height": height,
+        "width": width,
+        "blockdata_bank": blockdata_bank,
+        "blockdata_pointer": {"1": bytes[4], "2": bytes[5]},
+        "blockdata_address": blockdata_address,
+        "script_bank": script_bank,
+        "script_pointer": {"1": bytes[7], "2": bytes[8]},
+        "script_address": script_address,
+        "event_bank": event_bank,
+        "event_pointer": {"1": bytes[9], "2": bytes[10]},
+        "event_address": event_address,
+        "connections": connections,
+    }
+
 class MapBlockData:
     base_label = "MapBlockData_"
     maps_path = os.path.realpath(os.path.join(os.path.realpath("."), "../maps"))
@@ -5550,6 +5805,47 @@
     """parse crystal map event header byte structure thing"""
     return MapEventHeader(address, map_group=map_group, map_id=map_id, debug=debug, bank=bank)
 
+def old_parse_map_event_header_at(address, map_group=None, map_id=None, debug=True):
+    """parse crystal map event header byte structure thing"""
+    returnable = {}
+
+    bank = calculate_bank(address)
+
+    print "event header address is: " + hex(address)
+    filler1 = ord(rom[address])
+    filler2 = ord(rom[address+1])
+    returnable.update({"1": filler1, "2": filler2})
+    
+    #warps
+    warp_count = ord(rom[address+2])
+    warp_byte_count = warp_byte_size * warp_count
+    warps = rom_interval(address+3, warp_byte_count)
+    after_warps = address + 3 + warp_byte_count
+    returnable.update({"warp_count": warp_count, "warps": old_parse_warp_bytes(warps)})
+    
+    #triggers (based on xy location)
+    trigger_count = ord(rom[after_warps])
+    trigger_byte_count = trigger_byte_size * trigger_count
+    triggers = rom_interval(after_warps+1, trigger_byte_count)
+    after_triggers = after_warps + 1 + trigger_byte_count
+    returnable.update({"xy_trigger_count": trigger_count, "xy_triggers": old_parse_xy_trigger_bytes(triggers, bank=bank, map_group=map_group, map_id=map_id)})
+    
+    #signposts
+    signpost_count = ord(rom[after_triggers])
+    signpost_byte_count = signpost_byte_size * signpost_count
+    signposts = rom_interval(after_triggers+1, signpost_byte_count)
+    after_signposts = after_triggers + 1 + signpost_byte_count
+    returnable.update({"signpost_count": signpost_count, "signposts": old_parse_signpost_bytes(after_triggers+1, signpost_count, bank=bank, map_group=map_group, map_id=map_id)})
+  
+    #people events
+    people_event_count = ord(rom[after_signposts])
+    people_event_byte_count = people_event_byte_size * people_event_count
+    people_events_bytes = rom_interval(after_signposts+1, people_event_byte_count)
+    people_events = old_parse_people_event_bytes(people_events_bytes, address=after_signposts+1, map_group=map_group, map_id=map_id)
+    returnable.update({"people_event_count": people_event_count, "people_events": people_events})
+
+    return returnable
+
 class MapScriptHeader:
     """parses a script header
     
@@ -5660,6 +5956,61 @@
 def parse_map_script_header_at(address, map_group=None, map_id=None, debug=True):
     return MapScriptHeader(address, map_group=map_group, map_id=map_id, debug=debug)
 
+def old_parse_map_script_header_at(address, map_group=None, map_id=None, debug=True):
+    print "starting to parse the map's script header.."
+    #[[Number1 of pointers] Number1 * [2byte pointer to script][00][00]]
+    ptr_line_size = 4 #[2byte pointer to script][00][00]
+    trigger_ptr_cnt = ord(rom[address])
+    trigger_pointers = grouper(rom_interval(address+1, trigger_ptr_cnt * ptr_line_size, strings=False), count=ptr_line_size)
+    triggers = {}
+    for index, trigger_pointer in enumerate(trigger_pointers):
+        print "parsing a trigger header..."
+        byte1 = trigger_pointer[0]
+        byte2 = trigger_pointer[1]
+        ptr   = byte1 + (byte2 << 8)
+        trigger_address = calculate_pointer(ptr, calculate_bank(address))
+        trigger_script  = parse_script_engine_script_at(trigger_address, map_group=map_group, map_id=map_id)
+        triggers[index] = {
+            "script": trigger_script,
+            "address": trigger_address,
+            "pointer": {"1": byte1, "2": byte2},
+        }
+    
+    #bump ahead in the byte stream
+    address += trigger_ptr_cnt * ptr_line_size + 1
+    
+    #[[Number2 of pointers] Number2 * [hook number][2byte pointer to script]]
+    callback_ptr_line_size = 3
+    callback_ptr_cnt = ord(rom[address])
+    callback_ptrs = grouper(rom_interval(address+1, callback_ptr_cnt * callback_ptr_line_size, strings=False), count=callback_ptr_line_size)
+    callback_pointers = {}
+    callbacks = {}
+    for index, callback_line in enumerate(callback_ptrs):
+        print "parsing a callback header..."
+        hook_byte = callback_line[0] #1, 2, 3, 4, 5
+        callback_byte1 = callback_line[1]
+        callback_byte2 = callback_line[2]
+        callback_ptr = callback_byte1 + (callback_byte2 << 8)
+        callback_address = calculate_pointer(callback_ptr, calculate_bank(address))
+        callback_script = parse_script_engine_script_at(callback_address)
+        callback_pointers[len(callback_pointers.keys())] = [hook_byte, callback_ptr]
+        callbacks[index] = {
+            "script": callback_script,
+            "address": callback_address,
+            "pointer": {"1": callback_byte1, "2": callback_byte2},
+        }
+    
+    #XXX do these triggers/callbacks call asm or script engine scripts?
+    return {
+        #"trigger_ptr_cnt": trigger_ptr_cnt,
+        "trigger_pointers": trigger_pointers,
+        #"callback_ptr_cnt": callback_ptr_cnt,
+        #"callback_ptr_scripts": callback_ptrs,
+        "callback_pointers": callback_pointers,
+        "trigger_scripts": triggers,
+        "callback_scripts": callbacks,
+    }
+
 def old_parse_trainer_header_at(address, map_group=None, map_id=None, debug=True):
     bank = calculate_bank(address)
     bytes = rom_interval(address, 12, strings=False)
@@ -5776,7 +6127,7 @@
                 }
             if is_trainer:
                 print "parsing a trainer (person-event) at x=" + str(x) + " y=" + str(y)
-                parsed_trainer = parse_trainer_header_at(ptr_address, map_group=map_group, map_id=map_id)
+                parsed_trainer = old_parse_trainer_header_at(ptr_address, map_group=map_group, map_id=map_id)
                 extra_portion = {
                     "event_type": "trainer",
                     "trainer_data_address": ptr_address,
@@ -7366,8 +7717,6 @@
     #def test_parse_warp_bytes(self):
     #    pass #or raise NotImplementedError, bryan_message
     #def test_parse_xy_trigger_bytes(self):
-    #    pass #or raise NotImplementedError, bryan_message
-    #def test_parse_signpost_bytes(self):
     #    pass #or raise NotImplementedError, bryan_message
     #def test_parse_people_event_bytes(self):
     #    pass #or raise NotImplementedError, bryan_message