From 70280c0c3f64e41edaed8d2726c6472bec395f55 Mon Sep 17 00:00:00 2001 From: yenatch Date: Sat, 9 Feb 2013 04:10:50 -0500 Subject: Add some command-line interfaces for use w/ makefile Extras: -function to dump trainer pals -fix testing leftover in a compression function -keep load_rom() from getting in the way (relative address breaks extras) --- extras/gfx.py | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 4 deletions(-) (limited to 'extras/gfx.py') diff --git a/extras/gfx.py b/extras/gfx.py index 65eac7183..d28ac09be 100644 --- a/extras/gfx.py +++ b/extras/gfx.py @@ -8,10 +8,11 @@ from math import sqrt, floor, ceil from crystal import load_rom from pokemon_constants import pokemon_constants +from trainers import trainer_group_names - -rom = load_rom() +if __name__ != "__main__": + rom = load_rom() def mkdir_p(path): @@ -1032,7 +1033,7 @@ def compress_monster_frontpic(id, fileout): anim = open(fanim, 'rb').read() image = pic + anim - lz = Compressed(image, mode, 5) + lz = Compressed(image, mode, sizes[id-1]) out = '../gfx/pics/' + str(id).zfill(3) + '/front.lz' @@ -1081,6 +1082,8 @@ def grab_palettes(address, length = 0x80): def dump_monster_pals(): + rom = load_rom() + pals = 0xa8d6 pal_length = 0x4 for mon in range(251): @@ -1116,6 +1119,31 @@ def dump_monster_pals(): #print name+'ShinyPalette:'+spacing+' INCBIN "'+dir+filename+'"' +def dump_trainer_pals(): + rom = load_rom() + + pals = 0xb0d2 + pal_length = 0x4 + for trainer in range(67): + + name = trainer_group_names[trainer+1]['constant'].title().replace('_','') + num = str(trainer).zfill(3) + dir = 'gfx/trainers/' + + address = pals + trainer*pal_length + + pal_data = [] + for byte in range(pal_length): + pal_data.append(ord(rom[address])) + address += 1 + + filename = num+'.pal' + to_file('../'+dir+filename, pal_data) + + spacing = ' ' * (12 - len(name)) + print name+'Palette:'+spacing+' INCBIN"'+dir+filename+'"' + + def flatten(planar): """ @@ -1355,6 +1383,14 @@ def to_2bpp(filein, fileout=None, palout=None): to_file(fileout, image) +def png_to_lz(filein): + + name = os.path.splitext(filein)[0] + + to_2bpp(filein) + image = open(name+'.2bpp', 'rb').read() + to_file(name+'.lz', Compressed(image).output) + if __name__ == "__main__": parser = argparse.ArgumentParser() @@ -1362,12 +1398,57 @@ if __name__ == "__main__": parser.add_argument('arg1', nargs='?', metavar='arg1', type=str) parser.add_argument('arg2', nargs='?', metavar='arg2', type=str) parser.add_argument('arg3', nargs='?', metavar='arg3', type=str) + parser.add_argument('arg4', nargs='?', metavar='arg4', type=str) + parser.add_argument('arg5', nargs='?', metavar='arg5', type=str) args = parser.parse_args() debug = True - if args.cmd == 'de': + if args.cmd == 'png-to-lz': + # python gfx.py png-to-lz [--front anim(2bpp) | --vert] [png] + + # python gfx.py png-to-lz --front [anim(2bpp)] [png] + if args.arg1 == '--front': + + # front.png and tiles.png are combined before compression, + # so we have to pass in things like anim file and pic size + name = os.path.splitext(args.arg3)[0] + + to_2bpp(name+'.png', name+'.2bpp') + pic = open(name+'.2bpp', 'rb').read() + anim = open(args.arg2, 'rb').read() + size = int(sqrt(len(pic)/16)) # assume square pic + to_file(name+'.lz', Compressed(pic + anim, 'vert', size).output) + + + # python gfx.py png-to-lz --vert [png] + elif args.arg1 == '--vert': + + # others are vertically oriented (frontpics are always vertical) + + name = os.path.splitext(args.arg2)[0] + + to_2bpp(name+'.png', name+'.2bpp') + pic = open(name+'.2bpp', 'rb').read() + to_file(name+'.lz', Compressed(pic + anim, 'vert').output) + + + # python gfx.py png-to-lz [png] + else: + + # standard usage + + png_to_lz(args.arg1) + + elif args.cmd == 'png-to-2bpp': + to_2bpp(args.arg1) + + + elif args.cmd == 'de': # python gfx.py de [addr] [fileout] [mode] + + rom = load_rom() + addr = int(args.arg1,16) fileout = args.arg2 mode = args.arg3 @@ -1388,10 +1469,12 @@ if __name__ == "__main__": elif args.cmd == 'un': # python gfx.py un [address] [num_tiles] [filename] + rom = load_rom() get_uncompressed_gfx(int(args.arg1,16), int(args.arg2), args.arg3) elif args.cmd == 'pal': # python gfx.py pal [address] [length] + rom = load_rom() print grab_palettes(int(args.arg1,16), int(args.arg2)) elif args.cmd == 'png': @@ -1406,6 +1489,8 @@ if __name__ == "__main__": to_2bpp(args.arg1, args.arg2) #else: + else: + dump_trainer_pals() ## python gfx.py #decompress_all() #if debug: print 'decompressed known gfx to ../gfx/!' -- cgit v1.2.3 From e7762890aac4da72e75c7e7365c1cd924dadbc85 Mon Sep 17 00:00:00 2001 From: yenatch Date: Sat, 9 Feb 2013 06:22:08 -0500 Subject: Don't try to convert empty 2bpp files Also, make non-square images 1 tile wide Minor path fixes and cleanup --- extras/gfx.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'extras/gfx.py') diff --git a/extras/gfx.py b/extras/gfx.py index d28ac09be..44cd0482f 100644 --- a/extras/gfx.py +++ b/extras/gfx.py @@ -1212,12 +1212,13 @@ def to_png(filein, fileout=None, pal_file=None, height=None, width=None): Takes a planar 2bpp graphics file and converts it to png. """ - if fileout == None: fileout = ''.join(filein.split('.')[:-1]) + '.png' + if fileout == None: fileout = '.'.join(filein.split('.')[:-1]) + '.png' image = open(filein, 'rb').read() + if len(image) == 0: return 'empty image!' - # unless the pic is square, at least one dimension should be given + # unless the pic is square, at least one dimension should be given... if height == None and width == None: height = int(sqrt(len(image)*4)) @@ -1227,7 +1228,11 @@ def to_png(filein, fileout=None, pal_file=None, height=None, width=None): elif width == None: width = len(image)*4 / height - assert height * width == len(image)*4, 'Please specify dimensions for non-square image!' + # ...or it will become 1 tile wide + + if height * width != len(image)*4: + height = len(image)*4 / 8 + width = 8 # map it out @@ -1261,7 +1266,7 @@ def to_2bpp(filein, fileout=None, palout=None): Takes a png and converts it to planar 2bpp. """ - if fileout == None: fileout = ''.join(filein.split('.')[:-1]) + '.2bpp' + if fileout == None: fileout = '.'.join(filein.split('.')[:-1]) + '.2bpp' with open(filein, 'rb') as file: @@ -1489,8 +1494,6 @@ if __name__ == "__main__": to_2bpp(args.arg1, args.arg2) #else: - else: - dump_trainer_pals() ## python gfx.py #decompress_all() #if debug: print 'decompressed known gfx to ../gfx/!' -- cgit v1.2.3 From 80600f929193208e435e6ce833e4207a6cd5a382 Mon Sep 17 00:00:00 2001 From: yenatch Date: Sat, 9 Feb 2013 06:28:49 -0500 Subject: Infrastructure to dump pngs for 2bpp graphics --- extras/gfx.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'extras/gfx.py') diff --git a/extras/gfx.py b/extras/gfx.py index 44cd0482f..f7d6e96d7 100644 --- a/extras/gfx.py +++ b/extras/gfx.py @@ -1397,6 +1397,34 @@ def png_to_lz(filein): to_file(name+'.lz', Compressed(image).output) + + +def mass_to_png(): + # greyscale + for root, dirs, files in os.walk('../gfx/'): + for name in files: + print os.path.splitext(name), os.path.join(root, name) + if os.path.splitext(name)[1] == '.2bpp': + to_png(os.path.join(root, name)) + +def mass_to_colored_png(): + # only monster and trainer pics for now + for root, dirs, files in os.walk('../gfx/pics/'): + for name in files: + print os.path.splitext(name), os.path.join(root, name) + if os.path.splitext(name)[1] == '.2bpp': + if 'normal.pal' in files: + to_png(os.path.join(root, name), None, os.path.join(root, 'normal.pal')) + else: + to_png(os.path.join(root, name)) + for root, dirs, files in os.walk('../gfx/trainers/'): + for name in files: + print os.path.splitext(name), os.path.join(root, name) + if os.path.splitext(name)[1] == '.2bpp': + to_png(os.path.join(root, name), None, os.path.join(root, name[:-5] + '.pal')) + + + if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('cmd', nargs='?', metavar='cmd', type=str) @@ -1486,7 +1514,7 @@ if __name__ == "__main__": if '.2bpp' in args.arg1: if args.arg3 == 'greyscale': - to_png(args.arg1, args.arg2) + to_png(args.arg1, args.arg2)http://i.imgur.com/BMHkNuC.png else: to_png(args.arg1, args.arg2, args.arg3) -- cgit v1.2.3 From d1172e1fb67fe8bd9c33cc4ab0d45905167d4c53 Mon Sep 17 00:00:00 2001 From: yenatch Date: Sun, 10 Feb 2013 17:50:30 -0500 Subject: Add build target to mass-generate pngs from 2bpp files --- extras/gfx.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'extras/gfx.py') diff --git a/extras/gfx.py b/extras/gfx.py index f7d6e96d7..a67a301d6 100644 --- a/extras/gfx.py +++ b/extras/gfx.py @@ -1399,19 +1399,27 @@ def png_to_lz(filein): -def mass_to_png(): +def mass_to_png(debug=False): # greyscale for root, dirs, files in os.walk('../gfx/'): for name in files: - print os.path.splitext(name), os.path.join(root, name) + if debug: print os.path.splitext(name), os.path.join(root, name) if os.path.splitext(name)[1] == '.2bpp': to_png(os.path.join(root, name)) -def mass_to_colored_png(): +def mass_to_colored_png(debug=False): + # greyscale + for root, dirs, files in os.walk('../gfx/'): + if 'pics' not in root and 'trainers' not in root: + for name in files: + if debug: print os.path.splitext(name), os.path.join(root, name) + if os.path.splitext(name)[1] == '.2bpp': + to_png(os.path.join(root, name)) + # only monster and trainer pics for now for root, dirs, files in os.walk('../gfx/pics/'): for name in files: - print os.path.splitext(name), os.path.join(root, name) + if debug: print os.path.splitext(name), os.path.join(root, name) if os.path.splitext(name)[1] == '.2bpp': if 'normal.pal' in files: to_png(os.path.join(root, name), None, os.path.join(root, 'normal.pal')) @@ -1419,7 +1427,7 @@ def mass_to_colored_png(): to_png(os.path.join(root, name)) for root, dirs, files in os.walk('../gfx/trainers/'): for name in files: - print os.path.splitext(name), os.path.join(root, name) + if debug: print os.path.splitext(name), os.path.join(root, name) if os.path.splitext(name)[1] == '.2bpp': to_png(os.path.join(root, name), None, os.path.join(root, name[:-5] + '.pal')) @@ -1435,9 +1443,12 @@ if __name__ == "__main__": parser.add_argument('arg5', nargs='?', metavar='arg5', type=str) args = parser.parse_args() - debug = True + debug = False + + if args.cmd == 'dump-pngs': + mass_to_colored_png() - if args.cmd == 'png-to-lz': + elif args.cmd == 'png-to-lz': # python gfx.py png-to-lz [--front anim(2bpp) | --vert] [png] # python gfx.py png-to-lz --front [anim(2bpp)] [png] @@ -1514,7 +1525,7 @@ if __name__ == "__main__": if '.2bpp' in args.arg1: if args.arg3 == 'greyscale': - to_png(args.arg1, args.arg2)http://i.imgur.com/BMHkNuC.png + to_png(args.arg1, args.arg2) else: to_png(args.arg1, args.arg2, args.arg3) -- cgit v1.2.3 From 98d8914b62750ea7575a5c16ce954cc0bbedb825 Mon Sep 17 00:00:00 2001 From: yenatch Date: Mon, 11 Feb 2013 03:42:33 -0500 Subject: better dimension handling in 2bpp->png --- extras/gfx.py | 55 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 12 deletions(-) (limited to 'extras/gfx.py') diff --git a/extras/gfx.py b/extras/gfx.py index a67a301d6..c92f272af 100644 --- a/extras/gfx.py +++ b/extras/gfx.py @@ -1216,23 +1216,54 @@ def to_png(filein, fileout=None, pal_file=None, height=None, width=None): image = open(filein, 'rb').read() - if len(image) == 0: return 'empty image!' - - # unless the pic is square, at least one dimension should be given... + num_pixels = len(image) * 4 + + if num_pixels == 0: return 'empty image!' + + + # unless the pic is square, at least one dimension should be given - if height == None and width == None: - height = int(sqrt(len(image)*4)) - width = height + if width == None and height == None: + width = int(sqrt(num_pixels)) + height = width - elif height == None: height = len(image)*4 / width + elif height == None: + height = num_pixels / width - elif width == None: width = len(image)*4 / height + elif width == None: + width = num_pixels / height + + + # but try to see if it can be made rectangular + + if width * height != num_pixels: + + # look for possible combos of width/height that would form a rectangle + matches = [] + + # this is pretty inefficient, and there is probably a simpler way + for width in range(8,256+1,8): # we only want dimensions that fit in tiles + height = num_pixels / width + if height % 8 == 0: + matches.append((width, height)) + + # go for the most square image + width, height = sorted(matches, key=lambda (x,y): x+y)[0] # favors height + + + # if it can't, the only option is a width of 1 tile + + if width * height != num_pixels: + width = 8 + height = num_pixels / width + - # ...or it will become 1 tile wide + # if this still isn't rectangular, then the image isn't made of tiles - if height * width != len(image)*4: - height = len(image)*4 / 8 - width = 8 + # for now we'll just spit out a warning + if width * height != num_pixels: + print 'Warning! ' + fileout + ' is ' + width + 'x' + height + '(' + width*height + ' pixels),\n' +\ + 'but ' + filein + ' is ' + num_pixels + ' pixels!' # map it out -- cgit v1.2.3 From 0b8c5ef75b69521ccbd3e9b30431fba0ba2d569e Mon Sep 17 00:00:00 2001 From: yenatch Date: Mon, 11 Feb 2013 15:50:16 -0500 Subject: Finish off make target for png generation Now any existing lz files are converted to 2bpp, and all 2bpp files are converted to png. --- extras/gfx.py | 56 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 15 deletions(-) (limited to 'extras/gfx.py') diff --git a/extras/gfx.py b/extras/gfx.py index c92f272af..c641ab7f1 100644 --- a/extras/gfx.py +++ b/extras/gfx.py @@ -954,17 +954,6 @@ def decompress_misc(): def decompress_all(debug = False): """decompress all known compressed data in baserom""" - #mkdir_p('../gfx/') - #mkdir_p('../gfx/frontpics/') - #mkdir_p('../gfx/anim/') - #mkdir_p('../gfx/backpics/') - #mkdir_p('../gfx/trainers/') - #mkdir_p('../gfx/fx/') - #mkdir_p('../gfx/intro/') - #mkdir_p('../gfx/title/') - #mkdir_p('../gfx/tilesets/') - #mkdir_p('../gfx/misc/') - if debug: print 'fronts' decompress_monsters(front) if debug: print 'backs' @@ -1463,6 +1452,43 @@ def mass_to_colored_png(debug=False): to_png(os.path.join(root, name), None, os.path.join(root, name[:-5] + '.pal')) +def mass_decompress(debug=False): + for root, dirs, files in os.walk('../gfx/'): + for file in files: + if 'lz' in file: + if '/pics' in root: + if 'front' in file: + id = root.split('pics/')[1][:3] + if id != 'egg': + with open(root+'/'+file, 'rb') as lz: de = Decompressed(lz.read(), 'vert', sizes[int(id)-1]) + else: + with open(root+'/'+file, 'rb') as lz: de = Decompressed(lz.read(), 'vert', 4) + to_file(root+'/'+'front.2bpp', de.pic) + to_file(root+'/'+'tiles.2bpp', de.animtiles) + elif 'back' in file: + with open(root+'/'+file, 'rb') as lz: de = Decompressed(lz.read(), 'vert') + to_file(root+'/'+'back.2bpp', de.output) + elif '/trainers' in root or '/fx' in root: + with open(root+'/'+file, 'rb') as lz: de = Decompressed(lz.read(), 'vert') + to_file(root+'/'+file[:-3]+'.2bpp', de.output) + else: + with open(root+'/'+file, 'rb') as lz: de = Decompressed(lz.read()) + to_file(root+file[:-3]+'.2bpp', de.output) + +def append_terminator_to_lzs(directory): + # fix lzs that were extracted with a missing terminator + for root, dirs, files in os.walk(directory): + for file in files: + if '.lz' in file: + data = open(root+file,'rb').read() + if data[-1] != chr(0xff): + data += chr(0xff) + new = open(root+file,'wb') + new.write(data) + new.close() + + + if __name__ == "__main__": parser = argparse.ArgumentParser() @@ -1563,8 +1589,8 @@ if __name__ == "__main__": elif '.png' in args.arg1: to_2bpp(args.arg1, args.arg2) - #else: - ## python gfx.py - #decompress_all() - #if debug: print 'decompressed known gfx to ../gfx/!' + elif args.cmd == 'mass-decompress': + mass_decompress() + if debug: print 'decompressed known gfx to pokecrystal/gfx/!' + -- cgit v1.2.3