mirror of
https://gitlab.com/xCrystal/pokecrystal-board.git
synced 2024-11-16 11:27:33 -08:00
Edit some docstrings in /extras.
This commit is contained in:
parent
897d8b744c
commit
1120eaaaf5
@ -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.
|
||||
"""
|
||||
|
@ -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]
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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"
|
||||
@ -10,4 +15,4 @@ def rip_sprites_from_bank(bank, offset=0):
|
||||
file_handler.close()
|
||||
|
||||
rip_sprites_from_bank(0x30)
|
||||
rip_sprites_from_bank(0x31, offset=256)
|
||||
rip_sprites_from_bank(0x31, offset=256)
|
||||
|
@ -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)
|
||||
|
@ -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..
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user