Skip to content

Instantly share code, notes, and snippets.

@oupo
Last active November 19, 2017 14:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oupo/0a64d899b7d8dc976ad89d408d4f2f2f to your computer and use it in GitHub Desktop.
Save oupo/0a64d899b7d8dc976ad89d408d4f2f2f to your computer and use it in GitHub Desktop.
# NDSファイルの中のoverlayたちを展開して逆アセンブルする
# Usage: ruby nitrodis.rb <filename>.nds
require "fileutils"
OBJDUMP = 'C:/devkitPro/devkitARM/bin/arm-none-eabi-objdump.exe'
SIZEOF_OVR = 32
Fat = Struct.new(:start, :end)
Ovr = Struct.new(:id, :ramaddr, :ramsize, :bsssize, :start, :end, :file_id, :reserved)
def read_u32(f, ofs)
f.seek ofs
f.read(4).unpack("V")[0]
end
def read_u32_list(f, ofs, len)
f.seek ofs
f.read(4 * len).unpack("V*")
end
def read_cstr(f, ofs, len)
f.seek ofs
f.read(len).unpack("Z*")[0]
end
def read(f, ofs, bytes)
f.seek ofs
f.read(bytes)
end
def do_file(fname, bin, addr)
File.binwrite(fname+".orig", bin)
system "./DSDecmp", "-d", "-f", "lzovl", fname+".orig", fname
destfname = File.exist?(fname) ? fname : fname + ".orig"
system OBJDUMP, "-b", "binary", "-m", "arm",
"-Mforce-thumb", "--adjust-vma=#{addr}",
"-D", destfname, {1 => destfname + ".dis"}
end
fname = ARGV[0]
open(fname, "rb") do |f|
romname = read_cstr(f, 0, 12).gsub(" ", "")
arm9exe_start = read_u32(f, 0x20)
arm9exe_size = read_u32(f, 0x2c)
fat_off = read_u32(f, 0x48)
fat_size = read_u32(f, 0x4c)
num_files = fat_size / 8
arm9_overlay_off = read_u32(f, 0x50)
arm9_overlay_size = read_u32(f, 0x54)
num_overlay_9 = arm9_overlay_size / SIZEOF_OVR
fats = []
ovrs = []
num_files.times do |i|
s, e = read_u32_list(f, fat_off + i * 8, 2)
fats << Fat.new(s, e)
end
dirname = "overlay-#{romname}"
#FileUtils.rm_r dirname
FileUtils.mkdir_p dirname
bin = read(f, arm9exe_start, arm9exe_size)
do_file "#{dirname}/arm9exe", bin, 0x02000000
num_overlay_9.times do |i|
ovr = Ovr.new(*read_u32_list(f, arm9_overlay_off + i * SIZEOF_OVR, 8))
ovrs << ovr
fat = fats[ovr.file_id]
#puts "%d %08x %d %d %08x %08x %d %d %08x" % [ovr.file_id, ovr.ramaddr, ovr.ramsize, ovr.bsssize, ovr.start, ovr.end, fat.start, fat.end - fat.start, ovr.reserved]
#puts "%d %08x %d" % [ovr.file_id, ovr.ramaddr, ovr.ramsize]
bin = read(f, fat.start, fat.end - fat.start)
ovrfname = "#{dirname}/#{ovr.file_id}"
do_file ovrfname, bin, ovr.ramaddr
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment