mirror of
https://gitlab.com/xCrystal/pokecrystal-board.git
synced 2024-09-09 09:51:34 -07:00
Conflicts: constants.asm extras/crystal.py main.asm
This commit is contained in:
commit
7df002c3e2
21
.gitignore
vendored
21
.gitignore
vendored
@ -1,30 +1,31 @@
|
|||||||
#precompiled python
|
# precompiled python
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|
||||||
#compiled object file
|
# compiled object file
|
||||||
*.o
|
*.o
|
||||||
|
|
||||||
#no binaries
|
# no binaries
|
||||||
*.exe
|
*.exe
|
||||||
|
|
||||||
#roms
|
# roms
|
||||||
*.gbc
|
*.gbc
|
||||||
|
*.gb
|
||||||
|
|
||||||
#generated
|
# generated
|
||||||
*.tx
|
*.tx
|
||||||
|
|
||||||
#swap files for vim
|
# swap files for vim
|
||||||
.*.swp
|
.*.swp
|
||||||
|
|
||||||
#no data from extras/
|
# no data from extras/
|
||||||
extras/*.json
|
extras/*.json
|
||||||
|
|
||||||
#for any of the poor souls with save game files in their working directory
|
# for any of the poor souls with save game files in their working directory
|
||||||
baserom.sgm
|
baserom.sgm
|
||||||
baserom.sav
|
baserom.sav
|
||||||
pokered.sgm
|
pokered.sgm
|
||||||
pokered.sav
|
pokered.sav
|
||||||
|
|
||||||
#for vim configuration
|
# for vim configuration
|
||||||
#url: http://www.vim.org/scripts/script.php?script_id=441
|
# url: http://www.vim.org/scripts/script.php?script_id=441
|
||||||
.lvimrc
|
.lvimrc
|
||||||
|
9
Makefile
9
Makefile
@ -1,10 +1,15 @@
|
|||||||
.SUFFIXES: .asm .tx .o .gbc
|
.SUFFIXES: .asm .tx .o .gbc
|
||||||
|
|
||||||
TEXTFILES = text/sweethoney.tx
|
TEXTFILES = text/sweethoney.tx \
|
||||||
|
text/phone/bill.tx \
|
||||||
|
text/phone/elm.tx \
|
||||||
|
text/phone/mom.tx \
|
||||||
|
text/phone/trainers1.tx \
|
||||||
|
main.tx
|
||||||
|
|
||||||
all: pokecrystal.gbc
|
all: pokecrystal.gbc
|
||||||
|
|
||||||
pokecrystal.o: pokecrystal.asm main.tx constants.asm wram.asm ${TEXTFILES}
|
pokecrystal.o: pokecrystal.asm constants.asm wram.asm ${TEXTFILES}
|
||||||
rgbasm -o pokecrystal.o pokecrystal.asm
|
rgbasm -o pokecrystal.o pokecrystal.asm
|
||||||
|
|
||||||
.asm.tx:
|
.asm.tx:
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
_CRYSTAL EQU 1
|
_CRYSTAL EQU 1
|
||||||
|
|
||||||
|
FarCall EQU $08
|
||||||
|
Bankswitch EQU $10
|
||||||
|
|
||||||
dwb: MACRO
|
dwb: MACRO
|
||||||
dw \1
|
dw \1
|
||||||
db \2
|
db \2
|
||||||
@ -21,13 +24,18 @@ bigdw: MACRO
|
|||||||
callab: MACRO
|
callab: MACRO
|
||||||
ld hl, \1
|
ld hl, \1
|
||||||
ld a, BANK(\1)
|
ld a, BANK(\1)
|
||||||
rst $08
|
rst FarCall
|
||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
callba: MACRO
|
callba: MACRO
|
||||||
ld a, BANK(\1)
|
ld a, BANK(\1)
|
||||||
ld hl, \1
|
ld hl, \1
|
||||||
rst $08
|
rst FarCall
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
TX_RAM: MACRO
|
||||||
|
db 1
|
||||||
|
dw \1
|
||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
TX_FAR: MACRO
|
TX_FAR: MACRO
|
||||||
@ -36,6 +44,10 @@ TX_FAR: MACRO
|
|||||||
db BANK(\1)
|
db BANK(\1)
|
||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
|
RGB: MACRO
|
||||||
|
dw ((\3 << 10) | (\2 << 5) | (\1))
|
||||||
|
ENDM
|
||||||
|
|
||||||
; eventually replace with python macro
|
; eventually replace with python macro
|
||||||
note: MACRO
|
note: MACRO
|
||||||
db \1
|
db \1
|
||||||
@ -3360,3 +3372,20 @@ Unkn1Pals EQU $d000 ; 8 4-color palettes little endian)
|
|||||||
Unkn2Pals EQU $d040 ; 8 4-color palettes little endian)
|
Unkn2Pals EQU $d040 ; 8 4-color palettes little endian)
|
||||||
BGPals EQU $d080 ; 8 4-color palettes little endian)
|
BGPals EQU $d080 ; 8 4-color palettes little endian)
|
||||||
OBPals EQU $d0c0 ; 8 4-color palettes little endian)
|
OBPals EQU $d0c0 ; 8 4-color palettes little endian)
|
||||||
|
|
||||||
|
; oh my god this is hacky stop being so hacky
|
||||||
|
frame: MACRO
|
||||||
|
db \1
|
||||||
|
db \2
|
||||||
|
ENDM
|
||||||
|
setrepeat: MACRO
|
||||||
|
db $fe
|
||||||
|
db \1
|
||||||
|
ENDM
|
||||||
|
dorepeat: MACRO
|
||||||
|
db $fd
|
||||||
|
db \1
|
||||||
|
ENDM
|
||||||
|
endanim: MACRO
|
||||||
|
db $ff
|
||||||
|
ENDM
|
||||||
|
@ -30,9 +30,8 @@ After running those lines, `cp extras/output.txt main.asm` and run `git diff mai
|
|||||||
|
|
||||||
Unit tests cover most of the classes.
|
Unit tests cover most of the classes.
|
||||||
|
|
||||||
```python
|
```bash
|
||||||
import crystal
|
python tests.py
|
||||||
crystal.run_tests()
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Parsing a script at a known address
|
#### Parsing a script at a known address
|
||||||
|
@ -1,34 +1,30 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# author: Bryan Bishop <kanzure@gmail.com>
|
"""
|
||||||
# date: 2012-05-29
|
Finds shared functions between red/crystal.
|
||||||
# purpose: find shared functions between red/crystal
|
"""
|
||||||
|
|
||||||
from crystal import get_label_from_line, \
|
from crystal import (
|
||||||
get_address_from_line_comment, \
|
get_label_from_line,
|
||||||
AsmSection
|
get_address_from_line_comment,
|
||||||
|
AsmSection,
|
||||||
|
direct_load_rom,
|
||||||
|
direct_load_asm,
|
||||||
|
)
|
||||||
|
|
||||||
from romstr import RomStr, AsmList
|
from romstr import (
|
||||||
|
RomStr,
|
||||||
|
AsmList,
|
||||||
|
)
|
||||||
|
|
||||||
def load_rom(path):
|
def load_rom(path):
|
||||||
""" Loads a ROM file into an abbreviated RomStr object.
|
""" Loads a ROM file into an abbreviated RomStr object.
|
||||||
"""
|
"""
|
||||||
|
return direct_load_rom(filename=path)
|
||||||
fh = open(path, "r")
|
|
||||||
x = RomStr(fh.read())
|
|
||||||
fh.close()
|
|
||||||
|
|
||||||
return x
|
|
||||||
|
|
||||||
def load_asm(path):
|
def load_asm(path):
|
||||||
""" Loads source ASM into an abbreviated AsmList object.
|
""" Loads source ASM into an abbreviated AsmList object.
|
||||||
"""
|
"""
|
||||||
|
return direct_load_asm(filename=path)
|
||||||
fh = open(path, "r")
|
|
||||||
x = AsmList(fh.read().split("\n"))
|
|
||||||
fh.close()
|
|
||||||
|
|
||||||
return x
|
|
||||||
|
|
||||||
def findall_iter(sub, string):
|
def findall_iter(sub, string):
|
||||||
# url: http://stackoverflow.com/a/3874760/687783
|
# url: http://stackoverflow.com/a/3874760/687783
|
||||||
|
1412
extras/crystal.py
1412
extras/crystal.py
File diff suppressed because it is too large
Load Diff
14
extras/dump_sections
Executable file
14
extras/dump_sections
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# This wraps dump_sections.py so that other python scripts can import the
|
||||||
|
# functions. If dump_sections.py was instead called dump_sections, then other
|
||||||
|
# python source code would be unable to use the functions via import
|
||||||
|
# statements.
|
||||||
|
|
||||||
|
# figure out the path to this script
|
||||||
|
cwd="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
# construct the path to dump_sections.py
|
||||||
|
secpath=$cwd/dump_sections.py
|
||||||
|
|
||||||
|
# run dump_sections.py
|
||||||
|
$secpath $1
|
130
extras/dump_sections.py
Executable file
130
extras/dump_sections.py
Executable file
@ -0,0 +1,130 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Use this tool to dump an asm file for a new source code or disassembly project.
|
||||||
|
|
||||||
|
usage:
|
||||||
|
|
||||||
|
from dump_sections import dump_sections
|
||||||
|
|
||||||
|
output = dump_sections("../../butt.gbc")
|
||||||
|
|
||||||
|
file_handler = open("main.asm", "w")
|
||||||
|
file_handler.write(output)
|
||||||
|
file_handler.close()
|
||||||
|
|
||||||
|
You can also use this script from the shell, where it will look for
|
||||||
|
"baserom.gbc" in the current working path or whatever file path you pass in the
|
||||||
|
first positional argument.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
def upper_hex(input):
|
||||||
|
"""
|
||||||
|
Converts the input to an uppercase hex string.
|
||||||
|
"""
|
||||||
|
if input in [0, "0"]:
|
||||||
|
return "0"
|
||||||
|
elif input <= 0xF:
|
||||||
|
return ("%.x" % (input)).upper()
|
||||||
|
else:
|
||||||
|
return ("%.2x" % (input)).upper()
|
||||||
|
|
||||||
|
def format_bank_number(address, bank_size=0x4000):
|
||||||
|
"""
|
||||||
|
Returns a str of the hex number of the bank based on the address.
|
||||||
|
"""
|
||||||
|
return upper_hex(address / bank_size)
|
||||||
|
|
||||||
|
def calculate_bank_quantity(path, bank_size=0x4000):
|
||||||
|
"""
|
||||||
|
Returns the number of 0x4000 banks in the file at path.
|
||||||
|
"""
|
||||||
|
return float(os.lstat(path).st_size) / bank_size
|
||||||
|
|
||||||
|
def dump_section(bank_number, separator="\n\n"):
|
||||||
|
"""
|
||||||
|
Returns a str of a section header for the asm file.
|
||||||
|
"""
|
||||||
|
output = "SECTION \""
|
||||||
|
if bank_number in [0, "0"]:
|
||||||
|
output += "bank0\",HOME"
|
||||||
|
else:
|
||||||
|
output += "bank"
|
||||||
|
output += bank_number
|
||||||
|
output += "\",DATA,BANK[$"
|
||||||
|
output += bank_number
|
||||||
|
output += "]"
|
||||||
|
output += separator
|
||||||
|
return output
|
||||||
|
|
||||||
|
def dump_incbin_for_section(address, bank_size=0x4000, baserom="baserom.gbc", separator="\n\n"):
|
||||||
|
"""
|
||||||
|
Returns a str for an INCBIN line for an entire section.
|
||||||
|
"""
|
||||||
|
output = "INCBIN \""
|
||||||
|
output += baserom
|
||||||
|
output += "\",$"
|
||||||
|
output += upper_hex(address)
|
||||||
|
output += ",$"
|
||||||
|
output += upper_hex(bank_size)
|
||||||
|
output += separator
|
||||||
|
return output
|
||||||
|
|
||||||
|
def dump_sections(path, bank_size=0x4000, initial_bank=0, last_bank=None, separator="\n\n"):
|
||||||
|
"""
|
||||||
|
Returns a str of assembly source code. The source code delineates each
|
||||||
|
SECTION and includes bytes from the file specified by baserom.
|
||||||
|
"""
|
||||||
|
if not last_bank:
|
||||||
|
last_bank = calculate_bank_quantity(path, bank_size=bank_size)
|
||||||
|
|
||||||
|
if last_bank < initial_bank:
|
||||||
|
raise Exception("last_bank must be greater than or equal to initial_bank")
|
||||||
|
|
||||||
|
baserom_name = os.path.basename(path)
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
|
||||||
|
banks = range(initial_bank, last_bank)
|
||||||
|
|
||||||
|
for bank_number in banks:
|
||||||
|
address = bank_number * bank_size
|
||||||
|
|
||||||
|
# get a formatted hex number of the bank based on the address
|
||||||
|
formatted_bank_number = format_bank_number(address, bank_size=bank_size)
|
||||||
|
|
||||||
|
# SECTION
|
||||||
|
output += dump_section(formatted_bank_number, separator=separator)
|
||||||
|
|
||||||
|
# INCBIN a range of bytes from the ROM
|
||||||
|
output += dump_incbin_for_section(address, bank_size=bank_size, baserom=baserom_name, separator=separator)
|
||||||
|
|
||||||
|
# clean up newlines at the end of the output
|
||||||
|
if output[-2:] == "\n\n":
|
||||||
|
output = output[:-2]
|
||||||
|
output += "\n"
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("rompath", nargs="?", metavar="rompath", type=str)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# default to "baserom.gbc" in the current working directory
|
||||||
|
baserom = "baserom.gbc"
|
||||||
|
|
||||||
|
# but let the user override the default
|
||||||
|
if args.rompath:
|
||||||
|
baserom = args.rompath
|
||||||
|
|
||||||
|
# generate some asm
|
||||||
|
output = dump_sections(baserom)
|
||||||
|
|
||||||
|
# dump everything to stdout
|
||||||
|
sys.stdout.write(output)
|
||||||
|
|
@ -1,26 +1,28 @@
|
|||||||
#author: Bryan Bishop <kanzure@gmail.com>
|
# -*- coding: utf-8 -*-
|
||||||
#date: 2012-01-09
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from copy import copy, deepcopy
|
from copy import copy, deepcopy
|
||||||
from ctypes import c_int8
|
from ctypes import c_int8
|
||||||
import json
|
|
||||||
import random
|
import random
|
||||||
|
import json
|
||||||
|
|
||||||
spacing = "\t"
|
# New versions of json don't have read anymore.
|
||||||
|
if not hasattr(json, "read"):
|
||||||
|
json.read = json.loads
|
||||||
|
|
||||||
class XRomStr(str):
|
from romstr import RomStr
|
||||||
def __repr__(self):
|
|
||||||
return "RomStr(too long)"
|
|
||||||
|
|
||||||
def load_rom(filename="../baserom.gbc"):
|
def load_rom(filename="../baserom.gbc"):
|
||||||
"""loads bytes into memory"""
|
"""loads bytes into memory"""
|
||||||
global rom
|
global rom
|
||||||
file_handler = open(filename, "rb")
|
file_handler = open(filename, "rb")
|
||||||
rom = XRomStr(file_handler.read())
|
rom = RomStr(file_handler.read())
|
||||||
file_handler.close()
|
file_handler.close()
|
||||||
return rom
|
return rom
|
||||||
|
|
||||||
|
spacing = "\t"
|
||||||
|
|
||||||
temp_opt_table = [
|
temp_opt_table = [
|
||||||
[ "ADC A", 0x8f, 0 ],
|
[ "ADC A", 0x8f, 0 ],
|
||||||
[ "ADC B", 0x88, 0 ],
|
[ "ADC B", 0x88, 0 ],
|
||||||
@ -550,7 +552,7 @@ end_08_scripts_with = [
|
|||||||
0xc9, #ret
|
0xc9, #ret
|
||||||
###0xda, 0xe9, 0xd2, 0xc2, 0xca, 0xc3, 0x38, 0x30, 0x20, 0x28, 0x18, 0xd8, 0xd0, 0xc0, 0xc8, 0xc9
|
###0xda, 0xe9, 0xd2, 0xc2, 0xca, 0xc3, 0x38, 0x30, 0x20, 0x28, 0x18, 0xd8, 0xd0, 0xc0, 0xc8, 0xc9
|
||||||
]
|
]
|
||||||
relative_jumps = [0x38, 0x30, 0x20, 0x28, 0x18, 0xc3, 0xda, 0xc2]
|
relative_jumps = [0x38, 0x30, 0x20, 0x28, 0x18, 0xc3, 0xda, 0xc2]
|
||||||
relative_unconditional_jumps = [0xc3, 0x18]
|
relative_unconditional_jumps = [0xc3, 0x18]
|
||||||
|
|
||||||
call_commands = [0xdc, 0xd4, 0xc4, 0xcc, 0xcd]
|
call_commands = [0xdc, 0xd4, 0xc4, 0xcc, 0xcd]
|
||||||
@ -559,7 +561,7 @@ all_labels = {}
|
|||||||
def load_labels(filename="labels.json"):
|
def load_labels(filename="labels.json"):
|
||||||
global all_labels
|
global all_labels
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
all_labels = json.loads(open(filename, "r").read())
|
all_labels = json.read(open(filename, "r").read())
|
||||||
else:
|
else:
|
||||||
print "You must run crystal.scan_for_predefined_labels() to create \"labels.json\". Trying..."
|
print "You must run crystal.scan_for_predefined_labels() to create \"labels.json\". Trying..."
|
||||||
import crystal
|
import crystal
|
||||||
@ -601,10 +603,10 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, debug = False):
|
|||||||
#i = offset
|
#i = offset
|
||||||
#ad = end_address
|
#ad = end_address
|
||||||
#a, oa = current_byte_number
|
#a, oa = current_byte_number
|
||||||
|
|
||||||
load_labels()
|
load_labels()
|
||||||
load_rom()
|
load_rom()
|
||||||
|
|
||||||
bank_id = 0
|
bank_id = 0
|
||||||
if original_offset > 0x8000:
|
if original_offset > 0x8000:
|
||||||
bank_id = original_offset / 0x4000
|
bank_id = original_offset / 0x4000
|
||||||
|
@ -1043,14 +1043,16 @@ def decompress_monsters(type = front):
|
|||||||
# decompress
|
# decompress
|
||||||
monster = decompress_monster_by_id(id, type)
|
monster = decompress_monster_by_id(id, type)
|
||||||
if monster != None: # no unowns here
|
if monster != None: # no unowns here
|
||||||
filename = str(id+1).zfill(3) + '.2bpp' # 001.2bpp
|
|
||||||
if not type: # front
|
if not type: # front
|
||||||
folder = '../gfx/frontpics/'
|
filename = 'front.2bpp'
|
||||||
|
folder = '../gfx/pics/' + str(id+1).zfill(3) + '/'
|
||||||
to_file(folder+filename, monster.pic)
|
to_file(folder+filename, monster.pic)
|
||||||
folder = '../gfx/anim/'
|
filename = 'tiles.2bpp'
|
||||||
|
folder = '../gfx/pics/' + str(id+1).zfill(3) + '/'
|
||||||
to_file(folder+filename, monster.animtiles)
|
to_file(folder+filename, monster.animtiles)
|
||||||
else: # back
|
else: # back
|
||||||
folder = '../gfx/backpics/'
|
filename = 'back.2bpp'
|
||||||
|
folder = '../gfx/pics/' + str(id+1).zfill(3) + '/'
|
||||||
to_file(folder+filename, monster.pic)
|
to_file(folder+filename, monster.pic)
|
||||||
|
|
||||||
|
|
||||||
@ -1073,14 +1075,16 @@ def decompress_unowns(type = front):
|
|||||||
# decompress
|
# decompress
|
||||||
unown = decompress_unown_by_id(letter, type)
|
unown = decompress_unown_by_id(letter, type)
|
||||||
|
|
||||||
filename = str(unown_dex).zfill(3) + chr(ord('a') + letter) + '.2bpp' # 201a.2bpp
|
|
||||||
if not type: # front
|
if not type: # front
|
||||||
folder = '../gfx/frontpics/'
|
filename = 'front.2bpp'
|
||||||
|
folder = '../gfx/pics/' + str(unown_dex).zfill(3) + chr(ord('a') + letter) + '/'
|
||||||
to_file(folder+filename, unown.pic)
|
to_file(folder+filename, unown.pic)
|
||||||
|
filename = 'tiles.2bpp'
|
||||||
folder = '../gfx/anim/'
|
folder = '../gfx/anim/'
|
||||||
to_file(folder+filename, unown.animtiles)
|
to_file(folder+filename, unown.animtiles)
|
||||||
else: # back
|
else: # back
|
||||||
folder = '../gfx/backpics/'
|
filename = 'back.2bpp'
|
||||||
|
folder = '../gfx/pics/' + str(unown_dex).zfill(3) + chr(ord('a') + letter) + '/'
|
||||||
to_file(folder+filename, unown.pic)
|
to_file(folder+filename, unown.pic)
|
||||||
|
|
||||||
|
|
||||||
@ -1255,8 +1259,8 @@ def compress_file(filein, fileout, mode = 'horiz'):
|
|||||||
def compress_monster_frontpic(id, fileout):
|
def compress_monster_frontpic(id, fileout):
|
||||||
mode = 'vert'
|
mode = 'vert'
|
||||||
|
|
||||||
fpic = '../gfx/frontpics/' + str(id).zfill(3) + '.2bpp'
|
fpic = '../gfx/pics/' + str(id).zfill(3) + '/front.2bpp'
|
||||||
fanim = '../gfx/anim/' + str(id).zfill(3) + '.2bpp'
|
fanim = '../gfx/pics/' + str(id).zfill(3) + '/tiles.2bpp'
|
||||||
|
|
||||||
pic = open(fpic, 'rb').read()
|
pic = open(fpic, 'rb').read()
|
||||||
anim = open(fanim, 'rb').read()
|
anim = open(fanim, 'rb').read()
|
||||||
@ -1264,7 +1268,7 @@ def compress_monster_frontpic(id, fileout):
|
|||||||
|
|
||||||
lz = Compressed(image, mode, 5)
|
lz = Compressed(image, mode, 5)
|
||||||
|
|
||||||
out = '../gfx/frontpics/lz/' + str(id).zfill(3) + '.lz'
|
out = '../gfx/pics/' + str(id).zfill(3) + '/front.lz'
|
||||||
|
|
||||||
to_file(out, lz.output)
|
to_file(out, lz.output)
|
||||||
|
|
||||||
@ -1283,6 +1287,28 @@ def get_uncompressed_gfx(start, num_tiles, filename):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def hex_to_rgb(word):
|
||||||
|
red = word & 0b11111
|
||||||
|
word >>= 5
|
||||||
|
green = word & 0b11111
|
||||||
|
word >>= 5
|
||||||
|
blue = word & 0b11111
|
||||||
|
return (red, green, blue)
|
||||||
|
|
||||||
|
def grab_palettes(address, length = 0x80):
|
||||||
|
output = ''
|
||||||
|
for word in range(length/2):
|
||||||
|
color = ord(rom[address+1])*0x100 + ord(rom[address])
|
||||||
|
address += 2
|
||||||
|
color = hex_to_rgb(color)
|
||||||
|
red = str(color[0]).zfill(2)
|
||||||
|
green = str(color[1]).zfill(2)
|
||||||
|
blue = str(color[2]).zfill(2)
|
||||||
|
output += '\tRGB '+red+', '+green+', '+blue
|
||||||
|
output += '\n'
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('cmd', nargs='?', metavar='cmd', type=str)
|
parser.add_argument('cmd', nargs='?', metavar='cmd', type=str)
|
||||||
@ -1317,7 +1343,11 @@ if __name__ == "__main__":
|
|||||||
# python gfx.py un [address] [num_tiles] [filename]
|
# python gfx.py un [address] [num_tiles] [filename]
|
||||||
get_uncompressed_gfx(int(args.arg1,16), int(args.arg2), args.arg3)
|
get_uncompressed_gfx(int(args.arg1,16), int(args.arg2), args.arg3)
|
||||||
|
|
||||||
else:
|
elif args.cmd == 'pal':
|
||||||
# python gfx.py
|
# python gfx.py pal [address] [length]
|
||||||
decompress_all()
|
print grab_palettes(int(args.arg1,16), int(args.arg2))
|
||||||
if debug: print 'decompressed known gfx to ../gfx/!'
|
|
||||||
|
#else:
|
||||||
|
## python gfx.py
|
||||||
|
#decompress_all()
|
||||||
|
#if debug: print 'decompressed known gfx to ../gfx/!'
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
#!/usr/bin/python
|
# -*- coding: utf-8 -*-
|
||||||
# author: Bryan Bishop <kanzure@gmail.com>
|
|
||||||
# date: 2012-06-20
|
|
||||||
|
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
|
|
||||||
from romstr import RomStr, DisAsm, \
|
from romstr import (
|
||||||
relative_jumps, call_commands, \
|
RomStr,
|
||||||
relative_unconditional_jumps
|
relative_jumps,
|
||||||
|
call_commands,
|
||||||
|
relative_unconditional_jumps,
|
||||||
|
)
|
||||||
|
|
||||||
class RomGraph(nx.DiGraph):
|
class RomGraph(nx.DiGraph):
|
||||||
""" Graphs various functions pointing to each other.
|
""" Graphs various functions pointing to each other.
|
||||||
|
104
extras/interval_map.py
Normal file
104
extras/interval_map.py
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from bisect import bisect_left, bisect_right
|
||||||
|
from itertools import izip
|
||||||
|
|
||||||
|
class IntervalMap(object):
|
||||||
|
"""
|
||||||
|
This class maps a set of intervals to a set of values.
|
||||||
|
|
||||||
|
>>> i = IntervalMap()
|
||||||
|
>>> i[0:5] = "hello world"
|
||||||
|
>>> i[6:10] = "hello cruel world"
|
||||||
|
>>> print i[4]
|
||||||
|
"hello world"
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""initializes an empty IntervalMap"""
|
||||||
|
self._bounds = []
|
||||||
|
self._items = []
|
||||||
|
self._upperitem = None
|
||||||
|
|
||||||
|
def __setitem__(self, _slice, _value):
|
||||||
|
"""sets an interval mapping"""
|
||||||
|
assert isinstance(_slice, slice), 'The key must be a slice object'
|
||||||
|
|
||||||
|
if _slice.start is None:
|
||||||
|
start_point = -1
|
||||||
|
else:
|
||||||
|
start_point = bisect_left(self._bounds, _slice.start)
|
||||||
|
|
||||||
|
if _slice.stop is None:
|
||||||
|
end_point = -1
|
||||||
|
else:
|
||||||
|
end_point = bisect_left(self._bounds, _slice.stop)
|
||||||
|
|
||||||
|
if start_point>=0:
|
||||||
|
if start_point < len(self._bounds) and self._bounds[start_point]<_slice.start:
|
||||||
|
start_point += 1
|
||||||
|
|
||||||
|
if end_point>=0:
|
||||||
|
self._bounds[start_point:end_point] = [_slice.start, _slice.stop]
|
||||||
|
if start_point < len(self._items):
|
||||||
|
self._items[start_point:end_point] = [self._items[start_point], _value]
|
||||||
|
else:
|
||||||
|
self._items[start_point:end_point] = [self._upperitem, _value]
|
||||||
|
else:
|
||||||
|
self._bounds[start_point:] = [_slice.start]
|
||||||
|
if start_point < len(self._items):
|
||||||
|
self._items[start_point:] = [self._items[start_point], _value]
|
||||||
|
else:
|
||||||
|
self._items[start_point:] = [self._upperitem]
|
||||||
|
self._upperitem = _value
|
||||||
|
else:
|
||||||
|
if end_point>=0:
|
||||||
|
self._bounds[:end_point] = [_slice.stop]
|
||||||
|
self._items[:end_point] = [_value]
|
||||||
|
else:
|
||||||
|
self._bounds[:] = []
|
||||||
|
self._items[:] = []
|
||||||
|
self._upperitem = _value
|
||||||
|
|
||||||
|
def __getitem__(self,_point):
|
||||||
|
"""gets a value from the mapping"""
|
||||||
|
assert not isinstance(_point, slice), 'The key cannot be a slice object'
|
||||||
|
|
||||||
|
index = bisect_right(self._bounds, _point)
|
||||||
|
if index < len(self._bounds):
|
||||||
|
return self._items[index]
|
||||||
|
else:
|
||||||
|
return self._upperitem
|
||||||
|
|
||||||
|
def items(self):
|
||||||
|
"""returns an iterator with each item being
|
||||||
|
((low_bound, high_bound), value)
|
||||||
|
these items are returned in order"""
|
||||||
|
previous_bound = None
|
||||||
|
for (b, v) in izip(self._bounds, self._items):
|
||||||
|
if v is not None:
|
||||||
|
yield (previous_bound, b), v
|
||||||
|
previous_bound = b
|
||||||
|
if self._upperitem is not None:
|
||||||
|
yield (previous_bound, None), self._upperitem
|
||||||
|
|
||||||
|
def values(self):
|
||||||
|
"""returns an iterator with each item being a stored value
|
||||||
|
the items are returned in order"""
|
||||||
|
for v in self._items:
|
||||||
|
if v is not None:
|
||||||
|
yield v
|
||||||
|
if self._upperitem is not None:
|
||||||
|
yield self._upperitem
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
s = []
|
||||||
|
for b,v in self.items():
|
||||||
|
if v is not None:
|
||||||
|
s.append('[%r, %r] => %r'%(
|
||||||
|
b[0],
|
||||||
|
b[1],
|
||||||
|
v
|
||||||
|
))
|
||||||
|
return '{'+', '.join(s)+'}'
|
||||||
|
|
@ -1,4 +1,7 @@
|
|||||||
item_constants = {1: 'MASTER_BALL',
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
item_constants = {
|
||||||
|
1: 'MASTER_BALL',
|
||||||
2: 'ULTRA_BALL',
|
2: 'ULTRA_BALL',
|
||||||
3: 'BRIGHTPOWDER',
|
3: 'BRIGHTPOWDER',
|
||||||
4: 'GREAT_BALL',
|
4: 'GREAT_BALL',
|
||||||
@ -219,4 +222,20 @@ item_constants = {1: 'MASTER_BALL',
|
|||||||
246: 'HM_04',
|
246: 'HM_04',
|
||||||
247: 'HM_05',
|
247: 'HM_05',
|
||||||
248: 'HM_06',
|
248: 'HM_06',
|
||||||
249: 'HM_07'}
|
249: 'HM_07',
|
||||||
|
}
|
||||||
|
|
||||||
|
def find_item_label_by_id(id):
|
||||||
|
if id in item_constants.keys():
|
||||||
|
return item_constants[id]
|
||||||
|
else: return None
|
||||||
|
|
||||||
|
def generate_item_constants():
|
||||||
|
"""make a list of items to put in constants.asm"""
|
||||||
|
output = ""
|
||||||
|
for (id, item) in item_constants.items():
|
||||||
|
val = ("$%.2x"%id).upper()
|
||||||
|
while len(item)<13: item+= " "
|
||||||
|
output += item + " EQU " + val + "\n"
|
||||||
|
return output
|
||||||
|
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
""" Various label/line-related functions.
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Various label/line-related functions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from pointers import calculate_pointer, calculate_bank
|
from pointers import (
|
||||||
|
calculate_pointer,
|
||||||
|
calculate_bank,
|
||||||
|
)
|
||||||
|
|
||||||
def remove_quoted_text(line):
|
def remove_quoted_text(line):
|
||||||
"""get rid of content inside quotes
|
"""get rid of content inside quotes
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
moves = {
|
moves = {
|
||||||
0x01: "POUND",
|
0x01: "POUND",
|
||||||
0x02: "KARATE_CHOP",
|
0x02: "KARATE_CHOP",
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
pksv_gs = {
|
pksv_gs = {
|
||||||
0x00: "2call",
|
0x00: "2call",
|
||||||
@ -34,7 +35,7 @@ pksv_gs = {
|
|||||||
0x21: "checkitem",
|
0x21: "checkitem",
|
||||||
0x22: "givemoney",
|
0x22: "givemoney",
|
||||||
0x23: "takemoney",
|
0x23: "takemoney",
|
||||||
0x24: "checkmonkey",
|
0x24: "checkmoney",
|
||||||
0x25: "givecoins",
|
0x25: "givecoins",
|
||||||
0x26: "takecoins",
|
0x26: "takecoins",
|
||||||
0x27: "checkcoins",
|
0x27: "checkcoins",
|
||||||
@ -141,8 +142,8 @@ pksv_gs = {
|
|||||||
0xA3: "displaylocation",
|
0xA3: "displaylocation",
|
||||||
}
|
}
|
||||||
|
|
||||||
#see http://www.pokecommunity.com/showpost.php?p=4347261
|
# see http://www.pokecommunity.com/showpost.php?p=4347261
|
||||||
#NOTE: this has some updates that need to be back-ported to gold
|
# NOTE: this has some updates that need to be back-ported to gold
|
||||||
pksv_crystal = {
|
pksv_crystal = {
|
||||||
0x00: "2call",
|
0x00: "2call",
|
||||||
0x01: "3call",
|
0x01: "3call",
|
||||||
@ -179,7 +180,7 @@ pksv_crystal = {
|
|||||||
0x21: "checkitem",
|
0x21: "checkitem",
|
||||||
0x22: "givemoney",
|
0x22: "givemoney",
|
||||||
0x23: "takemoney",
|
0x23: "takemoney",
|
||||||
0x24: "checkmonkey",
|
0x24: "checkmoney",
|
||||||
0x25: "givecoins",
|
0x25: "givecoins",
|
||||||
0x26: "takecoins",
|
0x26: "takecoins",
|
||||||
0x27: "checkcoins",
|
0x27: "checkcoins",
|
||||||
@ -292,13 +293,14 @@ pksv_crystal = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#these cause the script to end; used in create_command_classes
|
#these cause the script to end; used in create_command_classes
|
||||||
pksv_crystal_more_enders = [0x03, 0x04, 0x05, 0x0C, 0x51, 0x53,
|
pksv_crystal_more_enders = [0x03, 0x04, 0x05, 0x0C, 0x51, 0x52,
|
||||||
0x8D, 0x8F, 0x90, 0x91, 0x92, 0x9B,
|
0x53, 0x8D, 0x8F, 0x90, 0x91, 0x92,
|
||||||
|
0x9B,
|
||||||
0xB2, #maybe?
|
0xB2, #maybe?
|
||||||
0xCC, #maybe?
|
0xCC, #maybe?
|
||||||
]
|
]
|
||||||
|
|
||||||
#these have no pksv names as of pksv 2.1.1
|
# these have no pksv names as of pksv 2.1.1
|
||||||
pksv_crystal_unknowns = [
|
pksv_crystal_unknowns = [
|
||||||
0x9F,
|
0x9F,
|
||||||
0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
""" Various functions related to pointer and address math. Mostly to avoid
|
# -*- coding: utf-8 -*-
|
||||||
depedency loops.
|
"""
|
||||||
|
Various functions related to pointer and address math. Mostly to avoid
|
||||||
|
depedency loops.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def calculate_bank(address):
|
def calculate_bank(address):
|
||||||
"""you are too lazy to divide on your own?"""
|
"""you are too lazy to divide on your own?"""
|
||||||
if type(address) == str:
|
if type(address) == str:
|
||||||
address = int(address, 16)
|
address = int(address, 16)
|
||||||
#if 0x4000 <= address <= 0x7FFF:
|
#if 0x4000 <= address <= 0x7FFF:
|
||||||
# raise Exception, "bank 1 does not exist"
|
# raise Exception, "bank 1 does not exist"
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
pokemon_constants = {
|
pokemon_constants = {
|
||||||
1: "BULBASAUR",
|
1: "BULBASAUR",
|
||||||
2: "IVYSAUR",
|
2: "IVYSAUR",
|
||||||
|
354
extras/romstr.py
354
extras/romstr.py
@ -1,8 +1,21 @@
|
|||||||
import sys, os, time, datetime, json
|
# -*- coding: utf-8 -*-
|
||||||
from gbz80disasm import opt_table
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import datetime
|
||||||
from ctypes import c_int8
|
from ctypes import c_int8
|
||||||
from copy import copy, deepcopy
|
from copy import copy
|
||||||
from labels import get_label_from_line, get_address_from_line_comment
|
import json
|
||||||
|
|
||||||
|
# New versions of json don't have read anymore.
|
||||||
|
if not hasattr(json, "read"):
|
||||||
|
json.read = json.loads
|
||||||
|
|
||||||
|
from labels import (
|
||||||
|
get_label_from_line,
|
||||||
|
get_address_from_line_comment,
|
||||||
|
)
|
||||||
|
|
||||||
relative_jumps = [0x38, 0x30, 0x20, 0x28, 0x18, 0xc3, 0xda, 0xc2, 0x32]
|
relative_jumps = [0x38, 0x30, 0x20, 0x28, 0x18, 0xc3, 0xda, 0xc2, 0x32]
|
||||||
relative_unconditional_jumps = [0xc3, 0x18]
|
relative_unconditional_jumps = [0xc3, 0x18]
|
||||||
@ -91,7 +104,7 @@ class RomStr(str):
|
|||||||
file_handler.close()
|
file_handler.close()
|
||||||
|
|
||||||
# load the labels from the file
|
# load the labels from the file
|
||||||
self.labels = json.loads(open(filename, "r").read())
|
self.labels = json.read(open(filename, "r").read())
|
||||||
|
|
||||||
def get_address_for(self, label):
|
def get_address_for(self, label):
|
||||||
""" Returns the address of a label. This is slow and could be improved
|
""" Returns the address of a label. This is slow and could be improved
|
||||||
@ -137,7 +150,7 @@ class RomStr(str):
|
|||||||
that will be parsed, so that large patches of data aren't parsed as
|
that will be parsed, so that large patches of data aren't parsed as
|
||||||
code.
|
code.
|
||||||
"""
|
"""
|
||||||
if type(address) == str and "0x" in address:
|
if type(address) in [str, unicode] and "0x" in address:
|
||||||
address = int(address, 16)
|
address = int(address, 16)
|
||||||
|
|
||||||
start_address = address
|
start_address = address
|
||||||
@ -166,333 +179,8 @@ class RomStr(str):
|
|||||||
elif end_address != None and size == None:
|
elif end_address != None and size == None:
|
||||||
size = end_address - start_address
|
size = end_address - start_address
|
||||||
|
|
||||||
return DisAsm(start_address=start_address, end_address=end_address, size=size, max_size=max_size, debug=debug, rom=self)
|
raise NotImplementedError("DisAsm was removed and never worked; hook up another disassembler please.")
|
||||||
|
#return DisAsm(start_address=start_address, end_address=end_address, size=size, max_size=max_size, debug=debug, rom=self)
|
||||||
class DisAsm:
|
|
||||||
""" z80 disassembler
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, start_address=None, end_address=None, size=None, max_size=0x4000, debug=True, rom=None):
|
|
||||||
assert start_address != None, "start_address must be given"
|
|
||||||
|
|
||||||
if rom == None:
|
|
||||||
file_handler = open("../baserom.gbc", "r")
|
|
||||||
bytes = file_handler.read()
|
|
||||||
file_handler.close()
|
|
||||||
rom = RomStr(bytes)
|
|
||||||
|
|
||||||
if debug not in [None, True, False]:
|
|
||||||
raise Exception, "debug param is invalid"
|
|
||||||
if debug == None:
|
|
||||||
debug = False
|
|
||||||
|
|
||||||
# get end_address and size in sync with each other
|
|
||||||
if end_address == None and size != None:
|
|
||||||
end_address = start_address + size
|
|
||||||
elif end_address != None and size == None:
|
|
||||||
size = end_address - start_address
|
|
||||||
elif end_address != None and size != None:
|
|
||||||
size = max(end_address - start_address, size)
|
|
||||||
end_address = start_address + size
|
|
||||||
|
|
||||||
# check that the bounds make sense
|
|
||||||
if end_address != None:
|
|
||||||
if end_address <= start_address:
|
|
||||||
raise Exception, "end_address is out of bounds"
|
|
||||||
elif (end_address - start_address) > max_size:
|
|
||||||
raise Exception, "end_address goes beyond max_size"
|
|
||||||
|
|
||||||
# check more edge cases
|
|
||||||
if not start_address >= 0:
|
|
||||||
raise Exception, "start_address must be at least 0"
|
|
||||||
elif end_address != None and not end_address >= 0:
|
|
||||||
raise Exception, "end_address must be at least 0"
|
|
||||||
|
|
||||||
self.rom = rom
|
|
||||||
self.start_address = start_address
|
|
||||||
self.end_address = end_address
|
|
||||||
self.size = size
|
|
||||||
self.max_size = max_size
|
|
||||||
self.debug = debug
|
|
||||||
|
|
||||||
self.parse()
|
|
||||||
|
|
||||||
def parse(self):
|
|
||||||
""" Disassembles stuff and things.
|
|
||||||
"""
|
|
||||||
|
|
||||||
rom = self.rom
|
|
||||||
start_address = self.start_address
|
|
||||||
end_address = self.end_address
|
|
||||||
max_size = self.max_size
|
|
||||||
debug = self.debug
|
|
||||||
|
|
||||||
bank_id = start_address / 0x4000
|
|
||||||
|
|
||||||
# [{"command": 0x20, "bytes": [0x20, 0x40, 0x50],
|
|
||||||
# "asm": "jp $5040", "label": "Unknown5040"}]
|
|
||||||
asm_commands = {}
|
|
||||||
|
|
||||||
offset = start_address
|
|
||||||
|
|
||||||
last_hl_address = None
|
|
||||||
last_a_address = None
|
|
||||||
used_3d97 = False
|
|
||||||
|
|
||||||
keep_reading = True
|
|
||||||
|
|
||||||
while (end_address != 0 and offset <= end_address) or keep_reading:
|
|
||||||
# read the current opcode byte
|
|
||||||
current_byte = ord(rom[offset])
|
|
||||||
current_byte_number = len(asm_commands.keys())
|
|
||||||
|
|
||||||
# setup this next/upcoming command
|
|
||||||
if offset in asm_commands.keys():
|
|
||||||
asm_command = asm_commands[offset]
|
|
||||||
else:
|
|
||||||
asm_command = {}
|
|
||||||
|
|
||||||
asm_command["address"] = offset
|
|
||||||
|
|
||||||
if not "references" in asm_command.keys():
|
|
||||||
# This counts how many times relative jumps reference this
|
|
||||||
# byte. This is used to determine whether or not to print out a
|
|
||||||
# label later.
|
|
||||||
asm_command["references"] = 0
|
|
||||||
|
|
||||||
# some commands have two opcodes
|
|
||||||
next_byte = ord(rom[offset+1])
|
|
||||||
|
|
||||||
if self.debug:
|
|
||||||
print "offset: \t\t" + hex(offset)
|
|
||||||
print "current_byte: \t\t" + hex(current_byte)
|
|
||||||
print "next_byte: \t\t" + hex(next_byte)
|
|
||||||
|
|
||||||
# all two-byte opcodes also have their first byte in there somewhere
|
|
||||||
if (current_byte in opt_table.keys()) or ((current_byte + (next_byte << 8)) in opt_table.keys()):
|
|
||||||
# this might be a two-byte opcode
|
|
||||||
possible_opcode = current_byte + (next_byte << 8)
|
|
||||||
|
|
||||||
# check if this is a two-byte opcode
|
|
||||||
if possible_opcode in opt_table.keys():
|
|
||||||
op_code = possible_opcode
|
|
||||||
else:
|
|
||||||
op_code = current_byte
|
|
||||||
|
|
||||||
op = opt_table[op_code]
|
|
||||||
|
|
||||||
opstr = op[0].lower()
|
|
||||||
optype = op[1]
|
|
||||||
|
|
||||||
if self.debug:
|
|
||||||
print "opstr: " + opstr
|
|
||||||
|
|
||||||
asm_command["type"] = "op"
|
|
||||||
asm_command["id"] = op_code
|
|
||||||
asm_command["format"] = opstr
|
|
||||||
asm_command["opnumberthing"] = optype
|
|
||||||
|
|
||||||
opstr2 = None
|
|
||||||
base_opstr = copy(opstr)
|
|
||||||
|
|
||||||
if "x" in opstr:
|
|
||||||
for x in range(0, opstr.count("x")):
|
|
||||||
insertion = ord(rom[offset + 1])
|
|
||||||
|
|
||||||
# Certain opcodes will have a local relative jump label
|
|
||||||
# here instead of a raw hex value, but this is
|
|
||||||
# controlled through asm output.
|
|
||||||
insertion = "$" + hex(insertion)[2:]
|
|
||||||
|
|
||||||
opstr = opstr[:opstr.find("x")].lower() + insertion + opstr[opstr.find("x")+1:].lower()
|
|
||||||
|
|
||||||
if op_code in relative_jumps:
|
|
||||||
target_address = offset + 2 + c_int8(ord(rom[offset + 1])).value
|
|
||||||
insertion = "asm_" + hex(target_address)
|
|
||||||
|
|
||||||
if str(target_address) in self.rom.labels.keys():
|
|
||||||
insertion = self.rom.labels[str(target_address)]
|
|
||||||
|
|
||||||
opstr2 = base_opstr[:base_opstr.find("x")].lower() + insertion + base_opstr[base_opstr.find("x")+1:].lower()
|
|
||||||
asm_command["formatted_with_labels"] = opstr2
|
|
||||||
asm_command["target_address"] = target_address
|
|
||||||
|
|
||||||
current_byte_number += 1
|
|
||||||
offset += 1
|
|
||||||
|
|
||||||
if "?" in opstr:
|
|
||||||
for y in range(0, opstr.count("?")):
|
|
||||||
byte1 = ord(rom[offset + 1])
|
|
||||||
byte2 = ord(rom[offset + 2])
|
|
||||||
|
|
||||||
number = byte1
|
|
||||||
number += byte2 << 8;
|
|
||||||
|
|
||||||
# In most cases, you can use a label here. Labels will
|
|
||||||
# be shown during asm output.
|
|
||||||
insertion = "$%.4x" % (number)
|
|
||||||
|
|
||||||
opstr = opstr[:opstr.find("?")].lower() + insertion + opstr[opstr.find("?")+1:].lower()
|
|
||||||
|
|
||||||
# This version of the formatted string has labels. In
|
|
||||||
# the future, the actual labels should be parsed
|
|
||||||
# straight out of the "main.asm" file.
|
|
||||||
target_address = number % 0x4000
|
|
||||||
insertion = "asm_" + hex(target_address)
|
|
||||||
|
|
||||||
if str(target_address) in self.rom.labels.keys():
|
|
||||||
insertion = self.rom.labels[str(target_address)]
|
|
||||||
|
|
||||||
opstr2 = base_opstr[:base_opstr.find("?")].lower() + insertion + base_opstr[base_opstr.find("?")+1:].lower()
|
|
||||||
asm_command["formatted_with_labels"] = opstr2
|
|
||||||
asm_command["target_address"] = target_address
|
|
||||||
|
|
||||||
current_byte_number += 2
|
|
||||||
offset += 2
|
|
||||||
|
|
||||||
# Check for relative jumps, construct the formatted asm line.
|
|
||||||
# Also set the usage of labels.
|
|
||||||
if current_byte in [0x18, 0x20] + relative_jumps: # jr or jr nz
|
|
||||||
# generate a label for the byte we're jumping to
|
|
||||||
target_address = offset + 1 + c_int8(ord(rom[offset])).value
|
|
||||||
|
|
||||||
if target_address in asm_commands.keys():
|
|
||||||
asm_commands[target_address]["references"] += 1
|
|
||||||
remote_label = "asm_" + hex(target_address)
|
|
||||||
asm_commands[target_address]["current_label"] = remote_label
|
|
||||||
asm_command["remote_label"] = remote_label
|
|
||||||
|
|
||||||
# Not sure how to set this, can't be True because an
|
|
||||||
# address referenced multiple times will use a label
|
|
||||||
# despite the label not necessarily being used in the
|
|
||||||
# output. The "use_remote_label" values should be
|
|
||||||
# calculated when rendering the asm output, based on
|
|
||||||
# which addresses and which op codes will be displayed
|
|
||||||
# (within the range).
|
|
||||||
asm_command["use_remote_label"] = "unknown"
|
|
||||||
else:
|
|
||||||
remote_label = "asm_" + hex(target_address)
|
|
||||||
|
|
||||||
# This remote address might not be part of this
|
|
||||||
# function.
|
|
||||||
asm_commands[target_address] = {
|
|
||||||
"references": 1,
|
|
||||||
"current_label": remote_label,
|
|
||||||
"address": target_address,
|
|
||||||
}
|
|
||||||
# Also, target_address can be negative (before the
|
|
||||||
# start_address that the user originally requested),
|
|
||||||
# and it shouldn't be shown on asm output because the
|
|
||||||
# intermediate bytes (between a negative target_address
|
|
||||||
# and start_address) won't be disassembled.
|
|
||||||
|
|
||||||
# Don't know yet if this remote address is part of this
|
|
||||||
# function or not. When the remote address is not part
|
|
||||||
# of this function, the label name should not be used,
|
|
||||||
# because that label will not be disassembled in the
|
|
||||||
# output, until the user asks it to.
|
|
||||||
asm_command["use_remote_label"] = "unknown"
|
|
||||||
asm_command["remote_label"] = remote_label
|
|
||||||
elif current_byte == 0x3e:
|
|
||||||
last_a_address = ord(rom[offset + 1])
|
|
||||||
|
|
||||||
# store the formatted string for the output later
|
|
||||||
asm_command["formatted"] = opstr
|
|
||||||
|
|
||||||
if current_byte == 0x21:
|
|
||||||
last_hl_address = byte1 + (byte2 << 8)
|
|
||||||
|
|
||||||
# this is leftover from pokered, might be meaningless
|
|
||||||
if current_byte == 0xcd:
|
|
||||||
if number == 0x3d97:
|
|
||||||
used_3d97 = True
|
|
||||||
|
|
||||||
if current_byte == 0xc3 or current_byte in relative_unconditional_jumps:
|
|
||||||
if current_byte == 0xc3:
|
|
||||||
if number == 0x3d97:
|
|
||||||
used_3d97 = True
|
|
||||||
|
|
||||||
# stop reading at a jump, relative jump or return
|
|
||||||
if current_byte in end_08_scripts_with:
|
|
||||||
is_data = False
|
|
||||||
|
|
||||||
if not self.has_outstanding_labels(asm_commands, offset):
|
|
||||||
keep_reading = False
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
keep_reading = True
|
|
||||||
else:
|
|
||||||
keep_reading = True
|
|
||||||
|
|
||||||
else:
|
|
||||||
# This shouldn't really happen, and means that this area of the
|
|
||||||
# ROM probably doesn't represent instructions.
|
|
||||||
asm_command["type"] = "data" # db
|
|
||||||
asm_command["value"] = current_byte
|
|
||||||
keep_reading = False
|
|
||||||
|
|
||||||
# save this new command in the list
|
|
||||||
asm_commands[asm_command["address"]] = asm_command
|
|
||||||
|
|
||||||
# jump forward by a byte
|
|
||||||
offset += 1
|
|
||||||
|
|
||||||
# also save the last command if necessary
|
|
||||||
if len(asm_commands.keys()) > 0 and asm_commands[asm_commands.keys()[-1]] is not asm_command:
|
|
||||||
asm_commands[asm_command["address"]] = asm_command
|
|
||||||
|
|
||||||
# store the set of commands on this object
|
|
||||||
self.asm_commands = asm_commands
|
|
||||||
|
|
||||||
self.end_address = offset + 1
|
|
||||||
self.last_address = self.end_address
|
|
||||||
|
|
||||||
def has_outstanding_labels(self, asm_commands, offset):
|
|
||||||
""" Checks if there are any labels that haven't yet been created.
|
|
||||||
""" # is this really necessary??
|
|
||||||
return False
|
|
||||||
|
|
||||||
def used_addresses(self):
|
|
||||||
""" Returns a list of unique addresses that this function will probably
|
|
||||||
call.
|
|
||||||
"""
|
|
||||||
addresses = set()
|
|
||||||
|
|
||||||
for (id, command) in self.asm_commands.items():
|
|
||||||
if command.has_key("target_address") and command["id"] in call_commands:
|
|
||||||
addresses.add(command["target_address"])
|
|
||||||
|
|
||||||
return addresses
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
""" ASM pretty printer.
|
|
||||||
"""
|
|
||||||
output = ""
|
|
||||||
|
|
||||||
for (key, line) in self.asm_commands.items():
|
|
||||||
# skip anything from before the beginning
|
|
||||||
if key < self.start_address:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# show a label
|
|
||||||
if line["references"] > 0 and "current_label" in line.keys():
|
|
||||||
if line["address"] == self.start_address:
|
|
||||||
output += "thing: ; " + hex(line["address"]) + "\n"
|
|
||||||
else:
|
|
||||||
output += "." + line["current_label"] + "\@ ; " + hex(line["address"]) + "\n"
|
|
||||||
|
|
||||||
# show the actual line
|
|
||||||
if line.has_key("formatted_with_labels"):
|
|
||||||
output += spacing + line["formatted_with_labels"]
|
|
||||||
elif line.has_key("formatted"):
|
|
||||||
output += spacing + line["formatted"]
|
|
||||||
#output += " ; to " +
|
|
||||||
output += "\n"
|
|
||||||
|
|
||||||
# show the next address after this chunk
|
|
||||||
output += "; " + hex(self.end_address)
|
|
||||||
|
|
||||||
return output
|
|
||||||
|
|
||||||
class AsmList(list):
|
class AsmList(list):
|
||||||
""" Simple wrapper to prevent all asm lines from being shown on screen.
|
""" Simple wrapper to prevent all asm lines from being shown on screen.
|
||||||
|
74
extras/test_dump_sections.py
Normal file
74
extras/test_dump_sections.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
try:
|
||||||
|
import unittest2 as unittest
|
||||||
|
except ImportError:
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
# check for things we need in unittest
|
||||||
|
if not hasattr(unittest.TestCase, 'setUpClass'):
|
||||||
|
sys.stderr.write("The unittest2 module or Python 2.7 is required to run this script.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
from dump_sections import (
|
||||||
|
upper_hex,
|
||||||
|
format_bank_number,
|
||||||
|
calculate_bank_quantity,
|
||||||
|
dump_section,
|
||||||
|
dump_incbin_for_section,
|
||||||
|
)
|
||||||
|
|
||||||
|
class TestDumpSections(unittest.TestCase):
|
||||||
|
def test_upper_hex(self):
|
||||||
|
number = 0x52
|
||||||
|
self.assertEquals(number, int("0x" + upper_hex(number), 16))
|
||||||
|
|
||||||
|
number = 0x1
|
||||||
|
self.assertEquals(number, int("0x" + upper_hex(number), 16))
|
||||||
|
|
||||||
|
number = 0x0
|
||||||
|
self.assertEquals(number, int("0x" + upper_hex(number), 16))
|
||||||
|
|
||||||
|
number = 0xAA
|
||||||
|
self.assertEquals(number, int("0x" + upper_hex(number), 16))
|
||||||
|
|
||||||
|
number = 0xFFFFAAA0000
|
||||||
|
self.assertEquals(number, int("0x" + upper_hex(number), 16))
|
||||||
|
|
||||||
|
def test_format_bank_number(self):
|
||||||
|
address = 0x0
|
||||||
|
self.assertEquals("0", format_bank_number(address))
|
||||||
|
|
||||||
|
address = 0x4000
|
||||||
|
self.assertEquals("1", format_bank_number(address))
|
||||||
|
|
||||||
|
address = 0x1FC000
|
||||||
|
self.assertEquals("7F", format_bank_number(address))
|
||||||
|
|
||||||
|
def test_dump_section(self):
|
||||||
|
self.assertIn("SECTION", dump_section(str(0)))
|
||||||
|
self.assertIn("HOME", dump_section(str(0)))
|
||||||
|
self.assertNotIn("HOME", dump_section(str(1)))
|
||||||
|
self.assertIn("DATA", dump_section(str(2)))
|
||||||
|
self.assertIn("BANK", dump_section(str(40)))
|
||||||
|
self.assertNotIn("BANK", dump_section(str(0)))
|
||||||
|
|
||||||
|
def test_dump_incbin_for_section(self):
|
||||||
|
self.assertIn("INCBIN", dump_incbin_for_section(0))
|
||||||
|
|
||||||
|
def test_dump_incbin_for_section_separator(self):
|
||||||
|
separator = "\n\n"
|
||||||
|
self.assertIn(separator, dump_incbin_for_section(0, separator=separator))
|
||||||
|
|
||||||
|
separator = "\t\t" # dumb
|
||||||
|
self.assertIn(separator, dump_incbin_for_section(0, separator=separator))
|
||||||
|
|
||||||
|
def test_dump_incbin_for_section_default(self):
|
||||||
|
rom = "baserom.gbc"
|
||||||
|
self.assertIn(rom, dump_incbin_for_section(0))
|
||||||
|
|
||||||
|
rom = "baserom"
|
||||||
|
self.assertIn(rom, dump_incbin_for_section(0x4000))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
1015
extras/tests.py
Normal file
1015
extras/tests.py
Normal file
File diff suppressed because it is too large
Load Diff
21
extras/type_constants.py
Normal file
21
extras/type_constants.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
type_constants = {
|
||||||
|
"NORMAL": 0x00,
|
||||||
|
"FIGHTING": 0x01,
|
||||||
|
"FLYING": 0x02,
|
||||||
|
"POISON": 0x03,
|
||||||
|
"GROUND": 0x04,
|
||||||
|
"ROCK": 0x05,
|
||||||
|
"BUG": 0x07,
|
||||||
|
"GHOST": 0x08,
|
||||||
|
"STEEL": 0x09,
|
||||||
|
"CURSE_T": 0x13,
|
||||||
|
"FIRE": 0x14,
|
||||||
|
"WATER": 0x15,
|
||||||
|
"GRASS": 0x16,
|
||||||
|
"ELECTRIC": 0x17,
|
||||||
|
"PSYCHIC": 0x18,
|
||||||
|
"ICE": 0x19,
|
||||||
|
"DRAGON": 0x1A,
|
||||||
|
"DARK": 0x1B,
|
||||||
|
}
|
BIN
gfx/misc/mobile_adapter.2bpp
Normal file
BIN
gfx/misc/mobile_adapter.2bpp
Normal file
Binary file not shown.
BIN
gfx/misc/mystery_gift.2bpp
Normal file
BIN
gfx/misc/mystery_gift.2bpp
Normal file
Binary file not shown.
BIN
gfx/misc/mystery_gift_jp.2bpp
Normal file
BIN
gfx/misc/mystery_gift_jp.2bpp
Normal file
Binary file not shown.
BIN
gfx/misc/pack.2bpp
Normal file
BIN
gfx/misc/pack.2bpp
Normal file
Binary file not shown.
10
gfx/pics/001/anim0.asm
Normal file
10
gfx/pics/001/anim0.asm
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
frame 1, 10
|
||||||
|
frame 2, 10
|
||||||
|
frame 1, 08
|
||||||
|
frame 2, 06
|
||||||
|
frame 4, 20
|
||||||
|
frame 3, 06
|
||||||
|
frame 0, 05
|
||||||
|
frame 5, 05
|
||||||
|
endanim
|
||||||
|
; 0xd089c
|
5
gfx/pics/001/anim1.asm
Normal file
5
gfx/pics/001/anim1.asm
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
frame 5, 05
|
||||||
|
frame 0, 05
|
||||||
|
frame 5, 05
|
||||||
|
endanim
|
||||||
|
; 0xd18a0
|
26
gfx/pics/001/bitmask.asm
Normal file
26
gfx/pics/001/bitmask.asm
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
; 0
|
||||||
|
db %01100000
|
||||||
|
db %10101101
|
||||||
|
db %00000001
|
||||||
|
db %00000000
|
||||||
|
; 1
|
||||||
|
db %00100000
|
||||||
|
db %10101101
|
||||||
|
db %00000001
|
||||||
|
db %00000000
|
||||||
|
; 2
|
||||||
|
db %01000010
|
||||||
|
db %00101001
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 3
|
||||||
|
db %00000000
|
||||||
|
db %00100001
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 4
|
||||||
|
db %10000100
|
||||||
|
db %00010000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 0xd26f9
|
21
gfx/pics/001/frames.asm
Normal file
21
gfx/pics/001/frames.asm
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
dw .frame1
|
||||||
|
dw .frame2
|
||||||
|
dw .frame3
|
||||||
|
dw .frame4
|
||||||
|
dw .frame5
|
||||||
|
.frame1
|
||||||
|
db $00 ; bitmask
|
||||||
|
db $19, $1a, $1b, $1c, $1d, $1e, $1f, $20
|
||||||
|
.frame2
|
||||||
|
db $01 ; bitmask
|
||||||
|
db $21, $1b, $22, $1d, $1e, $23, $24
|
||||||
|
.frame3
|
||||||
|
db $02 ; bitmask
|
||||||
|
db $25, $26, $1b, $27, $1e
|
||||||
|
.frame4
|
||||||
|
db $03 ; bitmask
|
||||||
|
db $1b, $1e
|
||||||
|
.frame5
|
||||||
|
db $04 ; bitmask
|
||||||
|
db $28, $29, $2a
|
||||||
|
; 0xd421e
|
6
gfx/pics/002/anim0.asm
Normal file
6
gfx/pics/002/anim0.asm
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
frame 0, 06
|
||||||
|
frame 1, 08
|
||||||
|
frame 2, 20
|
||||||
|
frame 1, 06
|
||||||
|
endanim
|
||||||
|
; 0xd08a5
|
8
gfx/pics/002/anim1.asm
Normal file
8
gfx/pics/002/anim1.asm
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
setrepeat 2
|
||||||
|
frame 0, 07
|
||||||
|
frame 3, 07
|
||||||
|
dorepeat 1
|
||||||
|
frame 0, 08
|
||||||
|
frame 1, 06
|
||||||
|
endanim
|
||||||
|
; 0xd18ad
|
19
gfx/pics/002/bitmask.asm
Normal file
19
gfx/pics/002/bitmask.asm
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
; 0
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %11000010
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 1
|
||||||
|
db %00000000
|
||||||
|
db %11000111
|
||||||
|
db %01110001
|
||||||
|
db %00011100
|
||||||
|
db %00000000
|
||||||
|
; 2
|
||||||
|
db %00000000
|
||||||
|
db %10000000
|
||||||
|
db %01100001
|
||||||
|
db %00011000
|
||||||
|
db %00000000
|
||||||
|
; 0xd2708
|
13
gfx/pics/002/frames.asm
Normal file
13
gfx/pics/002/frames.asm
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
dw .frame1
|
||||||
|
dw .frame2
|
||||||
|
dw .frame3
|
||||||
|
.frame1
|
||||||
|
db $00 ; bitmask
|
||||||
|
db $24, $25, $26
|
||||||
|
.frame2
|
||||||
|
db $01 ; bitmask
|
||||||
|
db $27, $28, $29, $2a, $2b, $2c, $2d, $2e, $2f, $30, $31, $32
|
||||||
|
.frame3
|
||||||
|
db $02 ; bitmask
|
||||||
|
db $33, $34, $35, $36, $37, $38
|
||||||
|
; 0xd423c
|
10
gfx/pics/003/anim0.asm
Normal file
10
gfx/pics/003/anim0.asm
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
frame 1, 10
|
||||||
|
frame 2, 35
|
||||||
|
frame 3, 08
|
||||||
|
frame 4, 08
|
||||||
|
setrepeat 2
|
||||||
|
frame 0, 10
|
||||||
|
frame 5, 10
|
||||||
|
dorepeat 5
|
||||||
|
endanim
|
||||||
|
; 0xd08b6
|
6
gfx/pics/003/anim1.asm
Normal file
6
gfx/pics/003/anim1.asm
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
frame 1, 35
|
||||||
|
frame 0, 13
|
||||||
|
frame 6, 13
|
||||||
|
frame 7, 13
|
||||||
|
endanim
|
||||||
|
; 0xd18b6
|
49
gfx/pics/003/bitmask.asm
Normal file
49
gfx/pics/003/bitmask.asm
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
; 0
|
||||||
|
db %00000000
|
||||||
|
db %00100000
|
||||||
|
db %00010000
|
||||||
|
db %00001000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 1
|
||||||
|
db %01110000
|
||||||
|
db %00111000
|
||||||
|
db %00011100
|
||||||
|
db %00001110
|
||||||
|
db %10000111
|
||||||
|
db %00000011
|
||||||
|
db %00000000
|
||||||
|
; 2
|
||||||
|
db %10001000
|
||||||
|
db %00001011
|
||||||
|
db %00100101
|
||||||
|
db %01000000
|
||||||
|
db %00111000
|
||||||
|
db %01111000
|
||||||
|
db %00000000
|
||||||
|
; 3
|
||||||
|
db %00001000
|
||||||
|
db %00001011
|
||||||
|
db %00000101
|
||||||
|
db %01000000
|
||||||
|
db %00110000
|
||||||
|
db %01111000
|
||||||
|
db %00000000
|
||||||
|
; 4
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %11000000
|
||||||
|
db %00000000
|
||||||
|
; 5
|
||||||
|
db %00100000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %00000100
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 0xd2732
|
32
gfx/pics/003/frames.asm
Normal file
32
gfx/pics/003/frames.asm
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
dw .frame1
|
||||||
|
dw .frame2
|
||||||
|
dw .frame3
|
||||||
|
dw .frame4
|
||||||
|
dw .frame5
|
||||||
|
dw .frame6
|
||||||
|
dw .frame7
|
||||||
|
.frame1
|
||||||
|
db $00 ; bitmask
|
||||||
|
db $31, $32, $33
|
||||||
|
.frame2
|
||||||
|
db $01 ; bitmask
|
||||||
|
db $34, $35, $36, $37, $38, $39, $3a, $3b, $3c, $3d, $3e, $3f
|
||||||
|
db $40, $41, $42, $43, $44, $45
|
||||||
|
.frame3
|
||||||
|
db $02 ; bitmask
|
||||||
|
db $46, $47, $48, $49, $4a, $4b, $4c, $4d, $4e, $4f, $50, $51
|
||||||
|
db $52, $53, $54, $55
|
||||||
|
.frame4
|
||||||
|
db $03 ; bitmask
|
||||||
|
db $46, $56, $57, $58, $4b, $4c, $4e, $59, $51, $5a, $5b, $54
|
||||||
|
db $55
|
||||||
|
.frame5
|
||||||
|
db $04 ; bitmask
|
||||||
|
db $5c, $5d
|
||||||
|
.frame6
|
||||||
|
db $05 ; bitmask
|
||||||
|
db $5e, $5f
|
||||||
|
.frame7
|
||||||
|
db $05 ; bitmask
|
||||||
|
db $60, $61
|
||||||
|
; 0xd4289
|
9
gfx/pics/004/anim0.asm
Normal file
9
gfx/pics/004/anim0.asm
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
frame 0, 04
|
||||||
|
frame 1, 08
|
||||||
|
frame 2, 24
|
||||||
|
frame 1, 08
|
||||||
|
frame 4, 10
|
||||||
|
frame 0, 10
|
||||||
|
frame 4, 10
|
||||||
|
endanim
|
||||||
|
; 0xd08c5
|
6
gfx/pics/004/anim1.asm
Normal file
6
gfx/pics/004/anim1.asm
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
setrepeat 2
|
||||||
|
frame 0, 06
|
||||||
|
frame 3, 06
|
||||||
|
dorepeat 1
|
||||||
|
endanim
|
||||||
|
; 0xd18bf
|
21
gfx/pics/004/bitmask.asm
Normal file
21
gfx/pics/004/bitmask.asm
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
; 0
|
||||||
|
db %00001100
|
||||||
|
db %00110001
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 1
|
||||||
|
db %11101111
|
||||||
|
db %00111101
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 2
|
||||||
|
db %01000000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 3
|
||||||
|
db %00000000
|
||||||
|
db %10000000
|
||||||
|
db %01100011
|
||||||
|
db %00000000
|
||||||
|
; 0xd2742
|
17
gfx/pics/004/frames.asm
Normal file
17
gfx/pics/004/frames.asm
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
dw .frame1
|
||||||
|
dw .frame2
|
||||||
|
dw .frame3
|
||||||
|
dw .frame4
|
||||||
|
.frame1
|
||||||
|
db $00 ; bitmask
|
||||||
|
db $19, $1a, $1b, $1c, $1d
|
||||||
|
.frame2
|
||||||
|
db $01 ; bitmask
|
||||||
|
db $14, $1e, $1f, $1a, $20, $21, $22, $1b, $23, $24, $1c, $1d
|
||||||
|
.frame3
|
||||||
|
db $02 ; bitmask
|
||||||
|
db $25
|
||||||
|
.frame4
|
||||||
|
db $03 ; bitmask
|
||||||
|
db $14, $26, $27, $28, $29
|
||||||
|
; 0xd42ac
|
9
gfx/pics/005/anim0.asm
Normal file
9
gfx/pics/005/anim0.asm
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
frame 3, 08
|
||||||
|
frame 2, 08
|
||||||
|
frame 3, 08
|
||||||
|
frame 2, 08
|
||||||
|
frame 1, 15
|
||||||
|
frame 3, 08
|
||||||
|
frame 4, 30
|
||||||
|
endanim
|
||||||
|
; 0xd08d4
|
8
gfx/pics/005/anim1.asm
Normal file
8
gfx/pics/005/anim1.asm
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
frame 3, 08
|
||||||
|
frame 4, 15
|
||||||
|
setrepeat 2
|
||||||
|
frame 0, 08
|
||||||
|
frame 1, 10
|
||||||
|
dorepeat 3
|
||||||
|
endanim
|
||||||
|
; 0xd18cc
|
19
gfx/pics/005/bitmask.asm
Normal file
19
gfx/pics/005/bitmask.asm
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
; 0
|
||||||
|
db %00000000
|
||||||
|
db %00001100
|
||||||
|
db %00000010
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 1
|
||||||
|
db %11011110
|
||||||
|
db %11110111
|
||||||
|
db %01011001
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 2
|
||||||
|
db %11011110
|
||||||
|
db %11110111
|
||||||
|
db %00111001
|
||||||
|
db %00001100
|
||||||
|
db %00000000
|
||||||
|
; 0xd2751
|
20
gfx/pics/005/frames.asm
Normal file
20
gfx/pics/005/frames.asm
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
dw .frame1
|
||||||
|
dw .frame2
|
||||||
|
dw .frame3
|
||||||
|
dw .frame4
|
||||||
|
.frame1
|
||||||
|
db $00 ; bitmask
|
||||||
|
db $24, $25, $26
|
||||||
|
.frame2
|
||||||
|
db $01 ; bitmask
|
||||||
|
db $00, $27, $28, $00, $00, $29, $2a, $2b, $2c, $2d, $2e, $2f
|
||||||
|
db $30, $31, $00, $32, $33
|
||||||
|
.frame3
|
||||||
|
db $02 ; bitmask
|
||||||
|
db $00, $27, $34, $35, $00, $29, $2a, $36, $37, $2d, $2e, $2f
|
||||||
|
db $38, $39, $00, $3a, $3b, $3c, $3d
|
||||||
|
.frame4
|
||||||
|
db $02 ; bitmask
|
||||||
|
db $00, $27, $34, $35, $00, $29, $2a, $36, $37, $2d, $2e, $2f
|
||||||
|
db $3e, $39, $00, $3f, $40, $3c, $3d
|
||||||
|
; 0xd42f2
|
8
gfx/pics/006/anim0.asm
Normal file
8
gfx/pics/006/anim0.asm
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
frame 0, 08
|
||||||
|
frame 1, 16
|
||||||
|
setrepeat 2
|
||||||
|
frame 2, 09
|
||||||
|
frame 1, 09
|
||||||
|
dorepeat 3
|
||||||
|
endanim
|
||||||
|
; 0xd08e1
|
6
gfx/pics/006/anim1.asm
Normal file
6
gfx/pics/006/anim1.asm
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
setrepeat 2
|
||||||
|
frame 0, 06
|
||||||
|
frame 3, 06
|
||||||
|
dorepeat 1
|
||||||
|
endanim
|
||||||
|
; 0xd18d5
|
25
gfx/pics/006/bitmask.asm
Normal file
25
gfx/pics/006/bitmask.asm
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
; 0
|
||||||
|
db %10011011
|
||||||
|
db %11000111
|
||||||
|
db %00100101
|
||||||
|
db %00000011
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 1
|
||||||
|
db %10011111
|
||||||
|
db %11000111
|
||||||
|
db %11100101
|
||||||
|
db %11110011
|
||||||
|
db %00111000
|
||||||
|
db %00111100
|
||||||
|
db %00000000
|
||||||
|
; 2
|
||||||
|
db %10000000
|
||||||
|
db %11000001
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 0xd2766
|
16
gfx/pics/006/frames.asm
Normal file
16
gfx/pics/006/frames.asm
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
dw .frame1
|
||||||
|
dw .frame2
|
||||||
|
dw .frame3
|
||||||
|
.frame1
|
||||||
|
db $00 ; bitmask
|
||||||
|
db $31, $32, $33, $34, $35, $36, $37, $38, $39, $3a, $3b, $3c
|
||||||
|
db $3d, $3e, $3f
|
||||||
|
.frame2
|
||||||
|
db $01 ; bitmask
|
||||||
|
db $31, $40, $41, $42, $34, $43, $36, $37, $44, $45, $3a, $3b
|
||||||
|
db $3c, $46, $05, $47, $3e, $3f, $48, $49, $4a, $4b, $05, $4c
|
||||||
|
db $4d, $05, $2a, $4e, $4f
|
||||||
|
.frame3
|
||||||
|
db $02 ; bitmask
|
||||||
|
db $50, $51, $52, $53
|
||||||
|
; 0xd432b
|
10
gfx/pics/007/anim0.asm
Normal file
10
gfx/pics/007/anim0.asm
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
frame 3, 10
|
||||||
|
setrepeat 2
|
||||||
|
frame 1, 09
|
||||||
|
frame 2, 05
|
||||||
|
dorepeat 2
|
||||||
|
frame 1, 10
|
||||||
|
frame 3, 15
|
||||||
|
frame 4, 05
|
||||||
|
endanim
|
||||||
|
; 0xd08f2
|
6
gfx/pics/007/anim1.asm
Normal file
6
gfx/pics/007/anim1.asm
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
setrepeat 2
|
||||||
|
frame 0, 05
|
||||||
|
frame 5, 05
|
||||||
|
dorepeat 1
|
||||||
|
endanim
|
||||||
|
; 0xd18de
|
26
gfx/pics/007/bitmask.asm
Normal file
26
gfx/pics/007/bitmask.asm
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
; 0
|
||||||
|
db %11100111
|
||||||
|
db %00011100
|
||||||
|
db %00000010
|
||||||
|
db %00000000
|
||||||
|
; 1
|
||||||
|
db %11100111
|
||||||
|
db %00011100
|
||||||
|
db %10001110
|
||||||
|
db %00000001
|
||||||
|
; 2
|
||||||
|
db %11000010
|
||||||
|
db %00001000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 3
|
||||||
|
db %10000000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 4
|
||||||
|
db %01000010
|
||||||
|
db %00001000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 0xd277a
|
22
gfx/pics/007/frames.asm
Normal file
22
gfx/pics/007/frames.asm
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
dw .frame1
|
||||||
|
dw .frame2
|
||||||
|
dw .frame3
|
||||||
|
dw .frame4
|
||||||
|
dw .frame5
|
||||||
|
.frame1
|
||||||
|
db $00 ; bitmask
|
||||||
|
db $03, $19, $1a, $1b, $1c, $1d, $1e, $1f, $20, $21
|
||||||
|
.frame2
|
||||||
|
db $01 ; bitmask
|
||||||
|
db $03, $19, $1a, $1b, $1c, $1d, $1e, $1f, $20, $21, $22, $23
|
||||||
|
db $24, $25
|
||||||
|
.frame3
|
||||||
|
db $02 ; bitmask
|
||||||
|
db $26, $27, $28, $29
|
||||||
|
.frame4
|
||||||
|
db $03 ; bitmask
|
||||||
|
db $28
|
||||||
|
.frame5
|
||||||
|
db $04 ; bitmask
|
||||||
|
db $26, $27, $29
|
||||||
|
; 0xd435a
|
8
gfx/pics/008/anim0.asm
Normal file
8
gfx/pics/008/anim0.asm
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
frame 0, 04
|
||||||
|
frame 2, 34
|
||||||
|
setrepeat 3
|
||||||
|
frame 0, 09
|
||||||
|
frame 1, 09
|
||||||
|
dorepeat 3
|
||||||
|
endanim
|
||||||
|
; 0xd08ff
|
6
gfx/pics/008/anim1.asm
Normal file
6
gfx/pics/008/anim1.asm
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
setrepeat 2
|
||||||
|
frame 0, 06
|
||||||
|
frame 3, 06
|
||||||
|
dorepeat 1
|
||||||
|
endanim
|
||||||
|
; 0xd18e7
|
19
gfx/pics/008/bitmask.asm
Normal file
19
gfx/pics/008/bitmask.asm
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
; 0
|
||||||
|
db %00000000
|
||||||
|
db %10001110
|
||||||
|
db %11100011
|
||||||
|
db %00111100
|
||||||
|
db %00001111
|
||||||
|
; 1
|
||||||
|
db %00000000
|
||||||
|
db %11000000
|
||||||
|
db %00110000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 2
|
||||||
|
db %10000000
|
||||||
|
db %01000001
|
||||||
|
db %00011000
|
||||||
|
db %00000000
|
||||||
|
db %00000000
|
||||||
|
; 0xd2789
|
14
gfx/pics/008/frames.asm
Normal file
14
gfx/pics/008/frames.asm
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
dw .frame1
|
||||||
|
dw .frame2
|
||||||
|
dw .frame3
|
||||||
|
.frame1
|
||||||
|
db $00 ; bitmask
|
||||||
|
db $24, $25, $26, $27, $28, $29, $2a, $2b, $2c, $2d, $2e, $2f
|
||||||
|
db $30, $31, $32, $33, $34
|
||||||
|
.frame2
|
||||||
|
db $01 ; bitmask
|
||||||
|
db $35, $36, $37, $38
|
||||||
|
.frame3
|
||||||
|
db $02 ; bitmask
|
||||||
|
db $39, $3a, $3b, $3c, $3d
|
||||||
|
; 0xd437d
|
6
gfx/pics/009/anim0.asm
Normal file
6
gfx/pics/009/anim0.asm
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
frame 1, 06
|
||||||
|
frame 2, 40
|
||||||
|
frame 3, 08
|
||||||
|
frame 1, 04
|
||||||
|
endanim
|
||||||
|
; 0xd0908
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user