Edit some docstrings in /extras.

This commit is contained in:
Kat Harrison 2013-06-23 12:43:16 -04:00
parent 897d8b744c
commit 1120eaaaf5
6 changed files with 135 additions and 66 deletions

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""
Finds shared functions between red/crystal.
Find shared functions between red/crystal.
"""
from crystal import (
@ -18,13 +18,13 @@ from romstr import (
def load_rom(path):
"""
Loads a ROM file into an abbreviated RomStr object.
Load a ROM file into an abbreviated RomStr object.
"""
return direct_load_rom(filename=path)
def load_asm(path):
"""
Loads source ASM into an abbreviated AsmList object.
Load source ASM into an abbreviated AsmList object.
"""
return direct_load_asm(filename=path)
@ -63,7 +63,8 @@ found_blobs = []
class BinaryBlob(object):
"""
Stores a label, line number, and addresses of a function from Pokémon Red.
Store a label, line number, and addresses of a function from Pokémon Red.
These details can be used to determine whether or not the function was
copied into Pokémon Crystal.
"""
@ -128,7 +129,7 @@ class BinaryBlob(object):
def parse_from_red(self):
"""
Reads bytes from Pokémon Red and stores them.
Read bytes from Pokémon Red and stores them.
"""
self.bytes = redrom[self.start_address : self.end_address + 1]
@ -146,7 +147,7 @@ class BinaryBlob(object):
def find_in_crystal(self):
"""
Checks whether or not the bytes appear in Pokémon Crystal.
Check whether or not the bytes appear in Pokémon Crystal.
"""
finditer = findall_iter(self.bytes, cryrom)
@ -160,7 +161,7 @@ class BinaryBlob(object):
def find_by_first_bytes(self):
"""
Finds this blob in Crystal based on the first n bytes.
Find this blob in Crystal based on the first n bytes.
"""
# how many bytes to match
@ -194,7 +195,7 @@ redsrc = load_asm(pokered_src_path)
def scan_red_asm(bank_stop=3, debug=True):
"""
Scans the ASM from Pokémon Red. Finds labels and objects. Does things.
Scan the ASM from Pokémon Red. Finds labels and objects. Does things.
Uses get_label_from_line and get_address_from_line_comment.
"""

View File

@ -13,6 +13,11 @@ if not hasattr(json, "read"):
json.read = json.loads
def load_rom(filename="../baserom.gbc"):
"""
Load the specified rom.
If no rom is given, load "../baserom.gbc".
"""
global rom
rom = bytearray(open(filename,'rb').read())
return rom
@ -557,6 +562,11 @@ call_commands = [0xdc, 0xd4, 0xc4, 0xcc, 0xcd]
all_labels = {}
def load_labels(filename="labels.json"):
"""
Load labels from specified file.
If no filename is given, loads 'labels.json'.
"""
global all_labels
# don't re-load labels each time
@ -588,21 +598,28 @@ def find_label(local_address, bank_id=0):
return None
def asm_label(address):
# why using a random value when you can use the address?
"""
Return the ASM label using the address.
"""
return ".ASM_" + hex(address)[2:]
def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_address=True, stop_at=[], debug = False):
#fs = current_address
#b = bank_byte
#in = input_data -- rom
#bank_size = byte_count
#i = offset
#ad = end_address
#a, oa = current_byte_number
def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_address=True, stop_at=[], debug=False):
"""
Output bank opcodes.
# stop_at can be used to supply a list of addresses to not disassemble
# over. This is useful if you know in advance that there are a lot of
# fall-throughs.
fs = current_address
b = bank_byte
in = input_data -- rom
bank_size = byte_count
i = offset
ad = end_address
a, oa = current_byte_number
stop_at can be used to supply a list of addresses to not disassemble
over. This is useful if you know in advance that there are a lot of
fall-throughs.
"""
load_labels()
load_rom()
@ -851,8 +868,9 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add
def has_outstanding_labels(byte_labels):
"""
If a label is used once in the asm output, then that means it has to be
called or specified later.
Check whether a label is used once in the asm output.
If so, then that means it has to be called or specified later.
"""
for label_line in byte_labels.keys():
real_line = byte_labels[label_line]

View File

@ -16,6 +16,9 @@ if __name__ != "__main__":
def mkdir_p(path):
"""
Make a directory at a given path.
"""
try:
os.makedirs(path)
except OSError as exc: # Python >2.5
@ -25,7 +28,9 @@ def mkdir_p(path):
def hex_dump(input, debug = True):
"""display hex dump in rows of 16 bytes"""
"""
Display hex dump in rows of 16 bytes.
"""
dump = ''
output = ''
@ -71,7 +76,9 @@ def hex_dump(input, debug = True):
def get_tiles(image):
"""split a 2bpp image into 8x8 tiles"""
"""
Split a 2bpp image into 8x8 tiles.
"""
tiles = []
tile = []
bytes_per_tile = 16
@ -91,7 +98,9 @@ def get_tiles(image):
def connect(tiles):
"""combine 8x8 tiles into a 2bpp image"""
"""
Combine 8x8 tiles into a 2bpp image.
"""
out = []
for tile in tiles:
for byte in tile:
@ -100,7 +109,9 @@ def connect(tiles):
def transpose(tiles):
"""transpose a tile arrangement along line y=x"""
"""
Transpose a tile arrangement along line y=x.
"""
# horizontal <-> vertical
# 00 01 02 03 04 05 00 06 0c 12 18 1e
@ -184,7 +195,10 @@ lowmax = 1 << 5 # standard 5-bit param
class Compressed:
"""compress 2bpp data"""
"""
Compress 2bpp data.
"""
def __init__(self, image = None, mode = 'horiz', size = None):
@ -231,7 +245,9 @@ class Compressed:
def compress(self):
"""incomplete, but outputs working compressed data"""
"""
Incomplete, but outputs working compressed data.
"""
self.address = 0
@ -308,10 +324,11 @@ class Compressed:
def scanRepeats(self):
"""works, but doesn't do flipped/reversed streams yet
"""
Works, but doesn't do flipped/reversed streams yet.
this takes up most of the compress time and only saves a few bytes
it might be more feasible to exclude it entirely"""
This takes up most of the compress time and only saves a few bytes
it might be more feasible to exclude it entirely."""
self.repeats = []
self.flips = []
@ -478,7 +495,7 @@ class Compressed:
while (ord(self.image[(self.address)+1]) == self.alts[num_alts&1]) & (num_alts <= max_length):
num_alts += 1
self.next()
# include the last alternated byte
# include the last alternated byte
num_alts += 1
self.address = original_address
if num_alts > lowmax:
@ -567,7 +584,8 @@ class Compressed:
class Decompressed:
"""parse compressed 2bpp data
"""
Parse compressed 2bpp data.
parameters:
[compressed 2bpp data]
@ -576,7 +594,8 @@ class Decompressed:
[start] (optional)
splits output into pic [size] and animation tiles if applicable
data can be fed in from rom if [start] is specified"""
data can be fed in from rom if [start] is specified
"""
def __init__(self, lz = None, mode = None, size = None, start = 0):
# todo: play nice with Compressed
@ -615,7 +634,9 @@ class Decompressed:
def decompress(self):
"""replica of crystal's decompression"""
"""
Replica of crystal's decompression.
"""
self.output = []
@ -674,19 +695,25 @@ class Decompressed:
self.getCurByte()
def doLiteral(self):
# copy 2bpp data directly
"""
Copy 2bpp data directly.
"""
for byte in range(self.length):
self.next()
self.output.append(self.byte)
def doIter(self):
# write one byte repeatedly
"""
Write one byte repeatedly.
"""
self.next()
for byte in range(self.length):
self.output.append(self.byte)
def doAlt(self):
# write alternating bytes
"""
Write alternating bytes.
"""
self.alts = []
self.next()
self.alts.append(self.byte)
@ -697,25 +724,27 @@ class Decompressed:
self.output.append(self.alts[byte&1])
def doZeros(self):
# write zeros
"""Write zeros."""
for byte in range(self.length):
self.output.append(0x00)
def doFlip(self):
# repeat flipped bytes from 2bpp output
# eg 11100100 -> 00100111
# quat 3 2 1 0 -> 0 2 1 3
"""Repeat flipped bytes from 2bpp output.
eg 11100100 -> 00100111
quat 3 2 1 0 -> 0 2 1 3
"""
for byte in range(self.length):
flipped = sum(1<<(7-i) for i in range(8) if self.output[self.displacement+byte]>>i&1)
self.output.append(flipped)
def doReverse(self):
# repeat reversed bytes from 2bpp output
"""Repeat reversed bytes from 2bpp output."""
for byte in range(self.length):
self.output.append(self.output[self.displacement-byte])
def doRepeat(self):
# repeat bytes from 2bpp output
"""Repeat bytes from 2bpp output."""
for byte in range(self.length):
self.output.append(self.output[self.displacement+byte])
@ -741,7 +770,9 @@ sizes = [
]
def make_sizes():
"""front pics have specified sizes"""
"""
Front pics have specified sizes.
"""
top = 251
base_stats = 0x51424
# print monster sizes
@ -955,7 +986,9 @@ def decompress_misc():
to_file(filename, gfx.output)
def decompress_all(debug = False):
"""decompress all known compressed data in baserom"""
"""
Decompress all known compressed data in baserom.
"""
if debug: print 'fronts'
decompress_monsters(front)
@ -988,7 +1021,9 @@ def decompress_all(debug = False):
def decompress_from_address(address, mode='horiz', filename = 'de.2bpp', size = None):
"""write decompressed data from an address to a 2bpp file"""
"""
Write decompressed data from an address to a 2bpp file.
"""
image = Decompressed(rom, mode, size, address)
to_file(filename, image.pic)
@ -1034,7 +1069,9 @@ def compress_monster_frontpic(id, fileout):
def get_uncompressed_gfx(start, num_tiles, filename):
"""grab tiles directly from rom and write to file"""
"""
Grab tiles directly from rom and write to file.
"""
bytes_per_tile = 0x10
length = num_tiles*bytes_per_tile
end = start + length
@ -1139,7 +1176,7 @@ def dump_trainer_pals():
def flatten(planar):
"""
Flattens planar 2bpp image data into a quaternary pixel map.
Flatten planar 2bpp image data into a quaternary pixel map.
"""
strips = []
for pair in range(len(planar)/2):
@ -1155,7 +1192,7 @@ def flatten(planar):
def to_lines(image, width):
"""
Converts a tiled quaternary pixel map to lines of quaternary pixels.
Convert a tiled quaternary pixel map to lines of quaternary pixels.
"""
tile = 8 * 8
@ -1208,8 +1245,8 @@ def png_pal(filename):
def to_png(filein, fileout=None, pal_file=None, height=None, width=None):
"""
Takes a planar 2bpp graphics file and converts it to png.
"""
Take a planar 2bpp graphics file and converts it to png.
"""
if fileout == None: fileout = '.'.join(filein.split('.')[:-1]) + '.png'

View File

@ -1,6 +1,11 @@
import gfx
def rip_sprites_from_bank(bank, offset=0):
"""
Rips sprites from specified bank.
Sprites are 4x4.
"""
file_handler = open("../gfx/overworld/bank" + str(hex(bank))[2:] + ".asm", "w")
for sprite in range(0 + offset, 256 + offset):
filename = "../gfx/overworld/" + str(sprite).zfill(3) + ".2bpp"

View File

@ -50,7 +50,7 @@ class RomStr(str):
@classmethod
def load(cls, filename=None, crystal=True, red=False):
"""
Loads a ROM into a RomStr.
Load a ROM into a RomStr.
"""
if crystal and not red and not filename:
file_handler = open("../baserom.gbc", "r")
@ -66,8 +66,10 @@ class RomStr(str):
def load_labels(self, filename="labels.json"):
"""
Loads labels from labels.json, or parses the source code file and
generates new labels.
Loads labels from labels.json.
(Or parses the source code file and
generates new labels.)
"""
filename = os.path.join(os.path.dirname(__file__), filename)
@ -114,8 +116,9 @@ class RomStr(str):
def get_address_for(self, label):
"""
Returns the address of a label. This is slow and could be improved
dramatically.
Return the address of a label.
This is slow and could be improved dramatically.
"""
label = str(label)
for address in self.labels.keys():
@ -137,7 +140,7 @@ class RomStr(str):
def interval(self, offset, length, strings=True, debug=True):
"""
returns hex values for the rom starting at offset until offset+length
Return hex values for the rom starting at offset until offset+length.
"""
returnable = []
for byte in self[offset:offset+length]:
@ -149,16 +152,17 @@ class RomStr(str):
def until(self, offset, byte, strings=True, debug=False):
"""
Returns hex values from rom starting at offset until the given byte.
Return hex values from rom starting at offset until the given byte.
"""
return self.interval(offset, self.find(chr(byte), offset) - offset, strings=strings)
def to_asm(self, address, end_address=None, size=None, max_size=0x4000, debug=None):
"""
Disassembles ASM at some address. This will stop disassembling when
either the end_address or size is met. Also, there's a maximum size
that will be parsed, so that large patches of data aren't parsed as
code.
Disassemble ASM at some address.
This will stop disassembling when either the end_address or size is
met. Also, there's a maximum size that will be parsed, so that large
patches of data aren't parsed as code.
"""
if type(address) in [str, unicode] and "0x" in address:
address = int(address, 16)

View File

@ -26,8 +26,10 @@ def main():
def skippable(func):
"""
Makes a function skippable by saving the state before and after the
function runs. Pass "skip=True" to the function to load the previous save
Makes a function skippable.
Saves the state before and after the function runs.
Pass "skip=True" to the function to load the previous save
state from when the function finished.
"""
def wrapped_function(*args, **kwargs):
@ -433,6 +435,8 @@ def handle_elm(starter_choice):
@skippable
def new_bark_level_grind(level):
"""
Do level grinding in New Bark.
Starting just outside of Elm's Lab, do some level grinding until the first
partymon level is equal to the given value..
"""