Skip to content

Commit

Permalink
support proc analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
laqieer committed Oct 1, 2018
1 parent f922e63 commit 83b6022
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.pyc
15 changes: 12 additions & 3 deletions Code Transplant Helper/code_transplant_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from enum import Enum
import sqlite3
import json
from proc_fe import *

class XType(Enum):
data = 0
Expand Down Expand Up @@ -57,8 +58,6 @@ def add_xrefs(ea, type):
xType = XType.code
else:
if xref.type == dr_R or xref.type == dr_W:
#TODO: Recoginze PROC

xType = XType.data

mirror = get_mirror(xref.to)
Expand All @@ -67,7 +66,14 @@ def add_xrefs(ea, type):
if mirror == Name(xref.to):
add_xrefs(xref.to, xType)
else:
#TODO: Handle PROC
if ea in procs:
for func in get_all_functions_in_proc(ea):
name = Name(func)
mirror = get_mirror(func)
tree.create_node(name, hex(long(func)), parent=hex(ea), data=Xref_node(name, hex(func), XType.proc, mirror))
if mirror == Name(func):
add_xrefs(func, XType.code)
return

for xref in DataRefsFrom(ea):
if (xref >= 0x2000000 and xref < 0x4000000) or (xref >= 0x8000000 and xref < 0xA000000):
Expand All @@ -76,6 +82,8 @@ def add_xrefs(ea, type):
xType = XType.data
mirror = get_mirror(xref)
tree.create_node(name, hex(xref), parent=hex(ea), data=Xref_node(name, hex(xref), xType, mirror))
if xref in procs:
add_xrefs(xref, XType.data)
else:
tree.remove_node(hex(ea))
break
Expand All @@ -95,6 +103,7 @@ def add_xrefs(ea, type):
with open(filename,'r') as load_f:
load_dict = json.load(load_f)
mirror = get_mirror(root.startEA)
procs = get_all_procs()
tree.create_node(fname, hex(root.startEA), data=Xref_node(fname, hex(root.startEA), XType.code, mirror))
if mirror == fname:
add_xrefs(root.startEA, XType.code)
Expand Down
57 changes: 57 additions & 0 deletions Code Transplant Helper/ida_gba.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# shared library for gba rom
# by laqieer
# 2018-10-01

from idc import *

def get_game_title():
"""
Get title of game
"""
return get_bytes(0x80000A0,12)

def get_game_code():
"""
Get code of game
This is the same code as the AGB-UTTD code which is printed on the package and sticker on (commercial) cartridges (excluding the leading "AGB-" part).
U Unique Code (usually "A" or "B" or special meaning)
TT Short Title (eg. "PM" for Pac Man)
D Destination/Language (usually "J" or "E" or "P" or specific language)
The first character (U) is usually "A" or "B", in detail:
A Normal game; Older titles (mainly 2001..2003)
B Normal game; Newer titles (2003..)
C Normal game; Not used yet, but might be used for even newer titles
F Famicom/Classic NES Series (software emulated NES games)
K Yoshi and Koro Koro Puzzle (acceleration sensor)
P e-Reader (dot-code scanner)
R Warioware Twisted (cartridge with rumble and z-axis gyro sensor)
U Boktai 1 and 2 (cartridge with RTC and solar sensor)
V Drill Dozer (cartridge with rumble)
The second/third characters (TT) are:
Usually an abbreviation of the game title (eg. "PM" for "Pac Man") (unless
that gamecode was already used for another game, then TT is just random)
The fourth character (D) indicates Destination/Language:
J Japan P Europe/Elsewhere F French S Spanish
E USA/English D German I Italian
"""
return get_bytes(0x80000AC,4)

def get_maker_code():
"""
Get maker code in cartridge header
Identifies the (commercial) developer. For example, "01"=Nintendo.
"""
return get_bytes(0x80000B0,2)

def get_software_version():
"""
Get software version in cartridge header
Version number of the game. Usually zero.
"""
return get_byte(0x80000BC)

def get_header_checksum():
"""
Get checksum of cartridge header
"""
return get_byte(0x80000BD)
9 changes: 9 additions & 0 deletions Code Transplant Helper/proc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// load this into ida database
// by laqieer
// 2018-10-01

struct proc {
unsigned short code;
unsigned short sarg;
unsigned short larg;
};
93 changes: 93 additions & 0 deletions Code Transplant Helper/proc_fe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# proc used in fire emblem
# by laqieer
# 2018-10-01

from ida_gba import *
from idaapi import *
from idc import *
from idautils import *

proc_create_functions = {
'AFEJ':0x8003A04, #FE6
'AE7J':0x8004370, #FE7J
'AE7E':0x8004494, #FE7U
'BE8J':0x8002BCC, #FE8J
'BE8E':0x8002C7C, #FE8U
}

def get_proc_create_function():
"""
Get the address of CreateProc()
"""
return proc_create_functions[get_game_code()]

def get_proc_create_function_blocking():
"""
Get the address of CreateProcBlocking()
"""
return 0x64 + proc_create_functions[get_game_code()]

def get_all_procs():
"""
Get the address of all procs in the rom
"""
proc_list = []

for xref in XrefsTo(get_proc_create_function()):
if xref.type == fl_CN or xref.type == fl_CF:
for i in DataRefsFrom(xref.frm - 4):
for proc_addr in DataRefsFrom(i):
if proc_list.count(proc_addr) == 0:
proc_list.append(proc_addr)

for xref in XrefsTo(get_proc_create_function_blocking()):
if xref.type == fl_CN or xref.type == fl_CF:
for i in DataRefsFrom(xref.frm - 4):
for proc_addr in DataRefsFrom(i):
if proc_list.count(proc_addr) == 0:
proc_list.append(proc_addr)

return proc_list

def show_procs_info():
"""
Show the total num and range of procs in the game
"""
proc_list = get_all_procs()
print "%d procs in total: from 0x%X to 0x%X" % (len(proc_list), min(proc_list), max(proc_list))
def get_end_addr(ea):
"""
Get end address of a proc
"""
return find_binary(ea, SEARCH_DOWN, "00 00 00 00 00 00 00 00")

def make_proc(ea):
"""
Make proc at a specific address
"""
create_struct(ea, 8, "proc")
end = get_end_addr(ea)
make_array(ea, (end - ea) / 8 + 1)

def make_all_procs():
"""
Make all procs in the game
"""
proc_list = get_all_procs()
for proc_addr in proc_list:
make_proc(proc_addr)
def get_all_functions_in_proc(ea):
"""
Get all functions in a proc
"""
functions = []
end = get_end_addr(ea)
for addr in range (ea, end, 4):
if get_dword(addr) == 2 or get_dword(addr) == 3:
func = get_dword(addr + 4) & 0x9FFFFFE
if func not in functions:
functions.append(func)
return functions

#show_procs_info()
#make_all_procs()

0 comments on commit 83b6022

Please sign in to comment.