Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # settings
- ROM_path = "pokeblue.gbc"
- MapHeaderBanks = 0xC23D
- MapHeaderPointers = 0x01AE
- Tilesets = 0xC7BE
- KeyItemBitfield = 0xE799
- # aliases
- class String
- def b ; self.unpack("C")[0] ; end
- def w ; self.unpack("S")[0] ; end
- end
- # >not a default method
- class Object
- def indices(obj)
- arr = []
- off = -1
- loop do
- idx = self[(off + 1)..-1].index(obj)
- break if(idx == nil)
- off += idx + 1
- arr << off
- end
- return arr
- end
- end
- def isKeyItem(id)
- # roughly same as the assembly
- # RAM dependent return true
- return false if(id > 0xC8) # TMs
- return true if(id > 0xC3) # HMs
- return true if(id > 0x78) # RAM
- if(id > 0x00) # bitfield lookup
- bitfield = ROM[KeyItemBitfield,15].unpack("b*")[0]
- bit = bitfield[id - 1]
- return [false,true][bit.to_i]
- end
- return true # RAM
- end
- # constants
- ROM = IO.binread(ROM_path)
- RAM = []
- BANKS = ROM.size / 0x4000
- BANKS.times do |i_bank|
- RAM[i_bank] = ROM[0x0000,0x4000] + ROM[i_bank * 0x4000,0x4000]
- end
- # check map IDs for combos
- hash_banks = {}
- to_tileset = {}
- 0x100.times do |i_map|
- map_header_bank = ROM[MapHeaderBanks + i_map * 0x01,0x01].b
- map_header_pointer = ROM[MapHeaderPointers + i_map * 0x02,0x02].w
- next if(map_header_bank >= BANKS)
- i_tileset = RAM[map_header_bank][map_header_pointer + 0x00,0x01].b
- map_width = RAM[map_header_bank][map_header_pointer + 0x02,0x01].b
- tileset = ROM[Tilesets + i_tileset * 0x0C,0x03].unpack("CS")
- bank = tileset[0]
- block = tileset[1] # pointer
- next if(bank >= BANKS)
- # bank -> block -> map_width -> i_map
- hash_banks[bank] = {} if(!hash_banks.has_key?(bank))
- hash_banks[bank][block] = {} if(!hash_banks[bank].has_key?(block))
- hash_banks[bank][block][map_width] = [] if(!hash_banks[bank][block].has_key?(map_width))
- hash_banks[bank][block][map_width] << i_map
- key = "#{bank}:#{block}"
- to_tileset[key] = [] if(!to_tileset.has_key?(key))
- to_tileset[key] << i_tileset if(!to_tileset[key].include?(i_tileset))
- end
- # some data variables
- valid = {
- 0x01 => [(0x00..0x00).to_a,(0x02..0x0F).to_a],
- 0x09 => [(0x00..0x08).to_a,(0x0A..0x0F).to_a],
- 0x03 => [[0x02],[0x06,0x07,0x0A,0x0B,0x0E,0x0F]],
- 0x0B => [[0x02,0x03,0x06,0x07,0x0A],[0x0E,0x0F]]
- }
- section = {
- "all" => (0..7).to_a,
- "top" => (0..3).to_a,
- "bottom" => (4..7).to_a,
- "left" => [0,2,4,6],
- "right" => [1,3,5,7],
- "top1" => (0..1).to_a,
- "top3" => (0..5).to_a,
- "tetris" => (0..4).to_a
- }
- section["topleft"] = section["top"] & section["left"]
- section["bottomleft"] = section["bottom"] & section["left"]
- section["bottomright"] = section["bottom"] & section["right"]
- section["top1left"] = section["top1"] & section["left"]
- section["top1right"] = section["top1"] & section["right"]
- section["top3right"] = section["top3"] & section["right"]
- # late addition
- 0x100.times do |pkmn|
- puts(pkmn)
- # iterate through combos
- log = File.open("logs/#{pkmn}.txt","w")
- hash_banks.each_pair do |bank,hash_blocks|
- next if([0x02,0x04,0x05].include?(bank))
- hash_blocks.each_pair do |block,hash_widths|
- pkmn_blocks = [] # pkmn blocks
- self_blocks = [] # self-terminating pkmn blocks
- end_blocks = {} # terminator blocks
- 0x100.times do |i_block|
- addr = block + i_block * 0x10
- next if(addr > 0x7FFF)
- tiles = RAM[bank][addr,0x10].unpack("C*")
- pkmn_indices = tiles.indices(pkmn) & valid.keys
- end_indices = tiles.indices(0x50)
- pkmn_indices.each do |index|
- next if((end_indices & valid[index][0]).size > 0)
- pkmn_blocks << [i_block,index]
- self_blocks << i_block if((end_indices & valid[index][1]).size > 0)
- end
- # categorized by pairs to simplify checking
- end_indices.each do |index|
- pair = index / 2
- end_blocks[pair] = [] if(!end_blocks.has_key?(pair))
- end_blocks[pair] << Regexp.escape(i_block.chr)
- end
- end
- next if(pkmn_blocks.size == 0)
- # further categorization
- section_blocks = {}
- section.each_pair do |name,pairs|
- section_blocks[name] = []
- pairs.each do |pair|
- section_blocks[name] += end_blocks[pair] if(end_blocks.has_key?(pair))
- end
- section_blocks[name] = section_blocks[name].join
- end
- bank_header = false
- # block outputs
- pkmn_blocks.each do |pkmn_block|
- i_block = pkmn_block[0]
- index = pkmn_block[1]
- index_qy = (index / 4) / 2
- index_qx = (index % 4) / 2
- index_q = index_qy * 2 + index_qx
- block_header = false
- results = 0
- (0x01..hash_widths.keys.max).each do |map_width|
- actual_width = map_width + 6
- regex = ""
- # first get all preceeding blocks
- # index_qy = 0 has extra row
- # index_qx = 0 bottom bottom bottomleft
- # index_qx = 1 bottomright bottom bottom
- if(index_qy == 0)
- regex += "[^#{section_blocks["bottomright"]}]" if(index_qx == 1)
- regex += "[^#{section_blocks["bottom"]}]{2}"
- regex += "[^#{section_blocks["bottomleft"]}]" if(index_qx == 0)
- regex += ".{#{actual_width - 3}}"
- end
- # index_qx = 0 all all left
- # index_qx = 1 right all all
- regex += "[^#{section_blocks["right"]}]" if(index_qx == 1)
- regex += "[^#{section_blocks["all"]}]{2}"
- regex += "[^#{section_blocks["left"]}]" if(index_qx == 0)
- regex += ".{#{actual_width - 3}}"
- # the pkmn block
- regex += Regexp.escape(i_block.chr)
- # now need to find valid screen compositions
- # if index_qy = 1, first two cant be in top or topleft
- addrs = []
- 8.times do |i|
- temp = regex
- if(i > 1)
- temp += "."
- temp += "(?<![#{section_blocks["top"]}])" if(index_qy == 1)
- temp += "."
- if(index_qy == 1)
- temp += "(?<![#{section_blocks["topleft"]}])" if(index_qx == 0)
- temp += "(?<![#{section_blocks["top"]}])" if(index_qx == 1)
- end
- end
- case(i)
- when(0)
- temp += "[#{section_blocks["all"]}]"
- temp += "(?<![#{section_blocks["top"]}])" if(index_qy == 1)
- when(1)
- temp += "."
- temp += "(?<![#{section_blocks["top"]}])" if(index_qy == 1)
- temp += "[#{section_blocks["left"]}]" if(index_qx == 0)
- temp += "[#{section_blocks["all"]}]" if(index_qx == 1)
- if(index_qy == 1)
- temp += "(?<![#{section_blocks["topleft"]}])" if(index_qx == 0)
- temp += "(?<![#{section_blocks["top"]}])" if(index_qx == 1)
- end
- when(2)
- temp += ".{#{actual_width - 2 - 1}}"
- temp += "[#{section_blocks["top3"]}]" if(index_q == 0)
- temp += "[#{section_blocks["top3right"]}]" if(index_q == 1)
- temp += "[#{section_blocks["all"]}]" if(index_q == 2)
- temp += "[#{section_blocks["right"]}]" if(index_q == 3)
- when(3)
- temp += ".{#{actual_width - 2}}"
- temp += "[#{section_blocks["top3"]}]" if(index_qy == 0)
- temp += "[#{section_blocks["all"]}]" if(index_qy == 1)
- when(4)
- temp += ".{#{actual_width - 2 + 1}}"
- temp += "[#{section_blocks["topleft"]}]" if(index_q == 0)
- temp += "[#{section_blocks["tetris"]}]" if(index_q == 1)
- temp += "[#{section_blocks["left"]}]" if(index_q == 2)
- temp += "[#{section_blocks["all"]}]" if(index_q == 3)
- when(5)
- break if(index_qy == 0)
- temp += ".{#{actual_width * 2 - 2 - 1}}"
- temp += "[#{section_blocks["top1"]}]" if(index_qx == 0)
- temp += "[#{section_blocks["top1right"]}]" if(index_qx == 1)
- when(6)
- temp += ".{#{actual_width * 2 - 2}}"
- temp += "[#{section_blocks["top1"]}]"
- when(7)
- break if(index_qx == 0)
- temp += ".{#{actual_width * 2 - 2 + 1}}"
- temp += "[#{section_blocks["top1left"]}]"
- end
- next if(temp.index("[]") != nil)
- temp = temp.gsub("[^]",".")
- found_addrs = RAM[bank].indices(Regexp.new(temp,Regexp::MULTILINE))
- found_addrs.each do |found_addr|
- addrs << found_addr if(!addrs.include?(found_addr))
- end
- end
- next if(addrs.size == 0)
- if(!bank_header)
- log.puts("//" * 16)
- log.puts("// TILESETS #{to_tileset["#{bank}:#{block}"].join(" ")}")
- list_maps = []
- hash_widths.each_value do |i_maps|
- i_maps.each do |i_map|
- list_maps << [i_map,isKeyItem(i_map) ? "*" : ""]
- end
- end
- log.print("// MAPS")
- list_maps.sort.each do |list_map|
- log.print(" #{list_map.join}")
- end
- log.puts
- log.puts("//" * 16)
- log.puts
- bank_header = true
- end
- if(!block_header)
- log.puts("// block #{i_block.to_s(16).upcase}")
- block_header = true
- end
- addrs = addrs.sort
- addrs.each do |addr|
- # level_offset = addr + map_width * (2 - index_qy) + 2
- # level_slot = index_qy * 8 + 4 + index_qx * 2
- # v_level = RAM[bank][level_offset,0x10].unpack("C*")[level_slot]
- log.print("insta(")
- log.print("tileset=#{to_tileset["#{bank}:#{block}"][0]},")
- log.print("offset=#{addr.to_s(16).rjust(4,"0")},")
- log.print("blocky=#{1 - index_qy},")
- log.print("blockx=#{index_qx},")
- log.print("width=#{map_width}")
- # log.print("level=#{v_level}")
- log.puts(")")
- # break
- end
- results += 1
- # break if(results == 10)
- end
- log.puts if(block_header)
- end
- if(bank_header)
- log.puts
- log.puts
- end
- end
- end
- log.close
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement