Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- tempclut = [(0, 0, 0, 255), (1, 1, 1, 255), (2, 2, 2, 255), (3, 3, 3, 255), (4, 4, 4, 255), (5, 5, 5, 255), (6, 6, 6, 255), (7, 7, 7, 255), (8, 8, 8, 255), (9, 9, 9, 255), (10, 10, 10, 255), (11, 11, 11, 255), (12, 12, 12, 255), (13, 13, 13, 255), (14, 14, 14, 255), (15, 15, 15, 255), (16, 16, 16, 255), (17, 17, 17, 255), (18, 18, 18, 255), (19, 19, 19, 255), (20, 20, 20, 255), (21, 21, 21, 255), (22, 22, 22, 255), (23, 23, 23, 255), (24, 24, 24, 255), (25, 25, 25, 255), (26, 26, 26, 255), (27, 27, 27, 255), (28, 28, 28, 255), (29, 29, 29, 255), (30, 30, 30, 255), (31, 31, 31, 255), (32, 32, 32, 255), (33, 33, 33, 255), (34, 34, 34, 255), (35, 35, 35, 255), (36, 36, 36, 255), (37, 37, 37, 255), (38, 38, 38, 255), (39, 39, 39, 255), (40, 40, 40, 255), (41, 41, 41, 255), (42, 42, 42, 255), (43, 43, 43, 255), (44, 44, 44, 255), (45, 45, 45, 255), (46, 46, 46, 255), (47, 47, 47, 255), (48, 48, 48, 255), (49, 49, 49, 255), (50, 50, 50, 255), (51, 51, 51, 255), (52, 52, 52, 255), (53, 53, 53, 255), (54, 54, 54, 255), (55, 55, 55, 255), (56, 56, 56, 255), (57, 57, 57, 255), (58, 58, 58, 255), (59, 59, 59, 255), (60, 60, 60, 255), (61, 61, 61, 255), (62, 62, 62, 255), (63, 63, 63, 255), (64, 64, 64, 255), (65, 65, 65, 255), (66, 66, 66, 255), (67, 67, 67, 255), (68, 68, 68, 255), (69, 69, 69, 255), (70, 70, 70, 255), (71, 71, 71, 255), (72, 72, 72, 255), (73, 73, 73, 255), (74, 74, 74, 255), (75, 75, 75, 255), (76, 76, 76, 255), (77, 77, 77, 255), (78, 78, 78, 255), (79, 79, 79, 255), (80, 80, 80, 255), (81, 81, 81, 255), (82, 82, 82, 255), (83, 83, 83, 255), (84, 84, 84, 255), (85, 85, 85, 255), (86, 86, 86, 255), (87, 87, 87, 255), (88, 88, 88, 255), (89, 89, 89, 255), (90, 90, 90, 255), (91, 91, 91, 255), (92, 92, 92, 255), (93, 93, 93, 255), (94, 94, 94, 255), (95, 95, 95, 255), (96, 96, 96, 255), (97, 97, 97, 255), (98, 98, 98, 255), (99, 99, 99, 255), (100, 100, 100, 255), (101, 101, 101, 255), (102, 102, 102, 255), (103, 103, 103, 255), (104, 104, 104, 255), (105, 105, 105, 255), (106, 106, 106, 255), (107, 107, 107, 255), (108, 108, 108, 255), (109, 109, 109, 255), (110, 110, 110, 255), (111, 111, 111, 255), (112, 112, 112, 255), (113, 113, 113, 255), (114, 114, 114, 255), (115, 115, 115, 255), (116, 116, 116, 255), (117, 117, 117, 255), (118, 118, 118, 255), (119, 119, 119, 255), (120, 120, 120, 255), (121, 121, 121, 255), (122, 122, 122, 255), (123, 123, 123, 255), (124, 124, 124, 255), (125, 125, 125, 255), (126, 126, 126, 255), (127, 127, 127, 255), (128, 128, 128, 255), (129, 129, 129, 255), (130, 130, 130, 255), (131, 131, 131, 255), (132, 132, 132, 255), (133, 133, 133, 255), (134, 134, 134, 255), (135, 135, 135, 255), (136, 136, 136, 255), (137, 137, 137, 255), (138, 138, 138, 255), (139, 139, 139, 255), (140, 140, 140, 255), (141, 141, 141, 255), (142, 142, 142, 255), (143, 143, 143, 255), (144, 144, 144, 255), (145, 145, 145, 255), (146, 146, 146, 255), (147, 147, 147, 255), (148, 148, 148, 255), (149, 149, 149, 255), (150, 150, 150, 255), (151, 151, 151, 255), (152, 152, 152, 255), (153, 153, 153, 255), (154, 154, 154, 255), (155, 155, 155, 255), (156, 156, 156, 255), (157, 157, 157, 255), (158, 158, 158, 255), (159, 159, 159, 255), (160, 160, 160, 255), (161, 161, 161, 255), (162, 162, 162, 255), (163, 163, 163, 255), (164, 164, 164, 255), (165, 165, 165, 255), (166, 166, 166, 255), (167, 167, 167, 255), (168, 168, 168, 255), (169, 169, 169, 255), (170, 170, 170, 255), (171, 171, 171, 255), (172, 172, 172, 255), (173, 173, 173, 255), (174, 174, 174, 255), (175, 175, 175, 255), (176, 176, 176, 255), (177, 177, 177, 255), (178, 178, 178, 255), (179, 179, 179, 255), (180, 180, 180, 255), (181, 181, 181, 255), (182, 182, 182, 255), (183, 183, 183, 255), (184, 184, 184, 255), (185, 185, 185, 255), (186, 186, 186, 255), (187, 187, 187, 255), (188, 188, 188, 255), (189, 189, 189, 255), (190, 190, 190, 255), (191, 191, 191, 255), (192, 192, 192, 255), (193, 193, 193, 255), (194, 194, 194, 255), (195, 195, 195, 255), (196, 196, 196, 255), (197, 197, 197, 255), (198, 198, 198, 255), (199, 199, 199, 255), (200, 200, 200, 255), (201, 201, 201, 255), (202, 202, 202, 255), (203, 203, 203, 255), (204, 204, 204, 255), (205, 205, 205, 255), (206, 206, 206, 255), (207, 207, 207, 255), (208, 208, 208, 255), (209, 209, 209, 255), (210, 210, 210, 255), (211, 211, 211, 255), (212, 212, 212, 255), (213, 213, 213, 255), (214, 214, 214, 255), (215, 215, 215, 255), (216, 216, 216, 255), (217, 217, 217, 255), (218, 218, 218, 255), (219, 219, 219, 255), (220, 220, 220, 255), (221, 221, 221, 255), (222, 222, 222, 255), (223, 223, 223, 255), (224, 224, 224, 255), (225, 225, 225, 255), (226, 226, 226, 255), (227, 227, 227, 255), (228, 228, 228, 255), (229, 229, 229, 255), (230, 230, 230, 255), (231, 231, 231, 255), (232, 232, 232, 255), (233, 233, 233, 255), (234, 234, 234, 255), (235, 235, 235, 255), (236, 236, 236, 255), (237, 237, 237, 255), (238, 238, 238, 255), (239, 239, 239, 255), (240, 240, 240, 255), (241, 241, 241, 255), (242, 242, 242, 255), (243, 243, 243, 255), (244, 244, 244, 255), (245, 245, 245, 255), (246, 246, 246, 255), (247, 247, 247, 255), (248, 248, 248, 255), (249, 249, 249, 255), (250, 250, 250, 255), (251, 251, 251, 255), (252, 252, 252, 255), (253, 253, 253, 255), (254, 254, 254, 255), (255, 255, 255, 255)]
- from operator import itemgetter
- import struct, os
- from PIL import Image
- BANK = 0x800
- VRAMSIZ = 0x64000
- ZONELIMIT = 0x4A800
- RGBAMO = 40
- RGBEND = 0x776D800
- RGBSIZ = 0x96000
- EMUEND = 0x756E800
- EMUSIZ = 0x181D60
- #EMUSIZ = 0x1FEB20
- OUT = "ex/"
- INFILE = "DEMO.PAC"
- RATELIST = {
- 0x7800: 12000,
- 0x7F00: 11714,
- }
- def mdir(directory):
- if not os.path.exists(directory):
- os.makedirs(directory)
- def getB(number=1):
- return int.from_bytes(rom.read(number), byteorder='little')
- def roundUp(num):
- out = BANK - (num % BANK)
- if out == BANK:
- out = 0
- return out
- def align(num):
- o = 4 - (num % 4)
- if o == 4:
- return 0
- return o
- def genVRAM(name):
- o = open(name, "wb+")
- o.write(bytes([0]*0x100000))
- return o
- def c2a(x,y):
- #coordinate to adress
- return (y << 11) + (x << 1)
- def w2c(word):
- #word to coords
- return (int((bin(word)[2:].zfill(16))[10:], 2) << 4 , int((bin(word)[2:].zfill(16))[1:10], 2))
- def getGFX(size, alloc):
- skip = alloc-size
- o = rom.read(size)
- rom.read(skip)
- return o
- def draw(what, where, x=0,y=0,w=0,h=0):
- if x|y|w|h == 0:
- where.write(what)
- return
- where.seek(c2a(x,y))
- w = w << 1
- for r in range(0, h*w, w):
- where.write(what[r:r+w])
- where.seek(-w+0x800, 1)
- return
- def getPalette(adr, infile):
- #print("gonna get pal from 0x{:X}".format(adr))
- infile.seek(adr)
- words = struct.unpack("<256H",infile.read(0x200))
- rgbas = []
- for num in range(0,len(words)):
- _R = ((words[num] & 0x1F)) * 8
- _G = ((words[num] & 0x3E0) >> 5) * 8
- _B = ((words[num] & 0x7C00) >> 10) * 8
- if (words[num] == 0):
- _A = 0
- else:
- _A = 0xFF
- rgbas.append((_R,_G,_B,_A))
- return rgbas
- def picture(name, nul, bpp, tp, x, y, w, h, clutW, vram):
- if clutW == 0xFFFF:
- clut_pool[clutW] = tempclut
- print("NOTICE ",name)
- if clutW not in clut_pool:
- #print("{:08X} not seen, adding".format(clutW))
- clut_pool[clutW] = getPalette(c2a(*w2c(clutW)), vram)
- #print(name, nul, bpp, tp, x, y, w, h, clutW)
- tpx = tp & 0xF
- #print("tpx<<7:",tpx << 7,"x",x)
- tpy = (tp >> 4) << 19
- pixels = []
- canvas = Image.new("RGBA", (w, h))
- if bpp == 0:
- w >>= 1
- vram.seek(tpy + (tpx << 7)+(x>>1) + (y << 11))
- else:
- vram.seek(tpy + (tpx << 7)+x + (y << 11))
- for r in range(0, h):
- if bpp == 4:
- for c in range(0, w):
- idx = ord(vram.read(1))
- pixels.append(clut_pool[clutW][idx])
- vram.seek(-w+0x800, 1)
- elif bpp == 0:
- for c in range(0, w):
- idx = ord(vram.read(1))
- pixels.append(clut_pool[clutW][idx&0xF])
- pixels.append(clut_pool[clutW][idx>>4])
- vram.seek(-w+0x800, 1)
- canvas.putdata(pixels)
- return canvas
- def testADPCM():
- rom.seek(-4, 1)
- rta = rom.tell()
- amask = 0xFFFF0F80FFFF00EE
- # 00001FC0000080FF
- # 0000DFEB00008CEE
- # 00005FCD0000A5FF
- # 0000DFEB000000FF
- # 00001FC0000080FF
- arslt = 0x00000F80000000EE
- first = False
- pcmque = []
- while True:
- esniff = getB(4)
- if first:
- if esniff == 0xFFFFFFFF:
- #print("ADPCM MATCH!!")
- adpcm = True
- break
- pcm1, pcm2, pcm_adr, pcm_size = struct.unpack("<HHII", rom.read(0xC))
- sniff = getB(8)
- if sniff & amask == arslt:
- print(" adr {:08X} size {:08X}".format(pcm_adr, pcm_size))
- pcmque.append((pcm_adr, pcm_size))
- first = True
- continue
- else:
- print("False positive. Not ADPCM!")
- if first:
- print("WEIRD THO")
- adpcm = False
- break
- rom.seek(rta)
- return adpcm
- def getADPCMlist():
- adpcmlist = []
- while True:
- sniff = getB(4)
- if sniff == 0xFFFFFFFF:
- break
- else:
- rom.seek(-4,1)
- _ = {}
- _["u0"], _["u1"], _["u2"], _["rate"], _["adr"], _["size"], _["u4"], _["u5"] = struct.unpack("<HHHHIIII", rom.read(0x18))
- adpcmlist.append(_)
- return adpcmlist
- def getRGB():
- o = []
- for p in range(0, RGBSIZ>>1):
- _ = getB(2)
- b = ((_ >> 10) & 0x1F) << 3
- g = ((_ >> 5) & 0x1F) << 3
- r = ((_ >> 0) & 0x1F) << 3
- o.append((r,g,b,255))
- return o
- with open(INFILE, "rb") as rom:
- mdir(OUT)
- fidx = 0
- while True:
- print("\n")
- root = rom.tell()
- check = getB(4)
- if check == 0x001F0001:
- VRAMFOLDER = OUT+"{:03d}_VRAM/".format(fidx)
- mdir(VRAMFOLDER)
- print("VRAM at 0x{:X}".format(root))
- both = 0
- while True:
- root = rom.tell()-4
- amount = getB(4)
- bonus1 = getB(4)
- bonus2 = getB(4)
- if bonus1 > 5:
- print("V case at {:08X}".format(root))
- #V case
- vram = genVRAM("tempVRAM.BIN")
- gfx_queue = []
- crd_queue = []
- for i in range(0, amount):
- crd_queue.append(struct.unpack("<HHHH", rom.read(0x8)))
- gfx_queue.append(struct.unpack("<II", rom.read(0x8)))
- rom.seek(roundUp(rom.tell()), 1)
- for i in range(0, amount):
- gfx = getGFX(*gfx_queue[i])
- crd = crd_queue[i]
- draw(gfx, vram, *crd)
- #draw(gfx, shard) < coming
- with open(VRAMFOLDER+"{:03d}.vram".format(fidx), "wb") as temp:
- vram.seek(0)
- temp.write(vram.read())
- both += 1
- else:
- print("N case at {:08X}".format(root))
- #N case
- pic_queue = []
- for i in range(0, amount):
- fname, nul, page, x, y, w, h, clutW = struct.unpack("<8sI6H", rom.read(0x18))
- tp = page & 0x1F
- bpp = page >> 5
- name = fname.decode("utf-8").rstrip('\x00')
- pic_queue.append((name, nul, bpp, tp, x, y, w, h, clutW))
- #print(name, "{:08X}".format(clutW))
- #print("{:16s}\t{:08X} {:04X} {:04X} {:04X} {:04X} {:04X} {:04X}".format(name,nul, id1, id2, id3, id4, id5, id6))
- if rom.tell() % BANK == 0:
- print("CLASH! +1")
- rom.read(1)
- both += 1
- print("case ends at {:08X}".format(rom.tell()))
- rom.seek(roundUp(rom.tell()), 1)
- if both == 2:
- break
- check = getB(4)
- clut_pool = {}
- for pic in pic_queue:
- picture(*pic, vram).save(VRAMFOLDER+pic[0]+".PNG")
- elif check == 0x00010003:
- print("LIST at 0x{:X}".format(root))
- LISTFOLDER = OUT+"{:03d}_LIST/".format(fidx)
- curf = LISTFOLDER
- mdir(curf)
- amo = getB(4)
- if amo == 0:
- rom.seek(roundUp(rom.tell()), 1)
- continue
- entryque = []
- for i in range(0,amo):
- _foname, findex, _finame, fadr, fsize = struct.unpack("<4sI16sII", rom.read(0x20))
- try:
- foname = _foname.decode("utf-8").rstrip('\x00')
- except UnicodeDecodeError:
- fonum = "{:08X}".format(struct.unpack("<I", _foname)[0])
- if fonum == "000000FD":
- foname = "PRM"
- else:
- foname = fonum#str(_foname)
- try:
- finame = _finame.decode("utf-8").rstrip('\x00')
- except UnicodeDecodeError:
- finame = "{:08X}".format(struct.unpack("<I", _finame)[0])#str(_finame)
- if finame == " ":
- finame = "NONAME.non"
- if "." not in finame:
- finame += ".s3d"
- estr = "{:8s} {:12s} {:08X}".format(foname,finame,findex)
- entryque.append([fadr, estr, fsize, foname, finame])
- for ofile in range(0,len(entryque)):
- cf = entryque[ofile]
- fo_outname = curf+cf[3]+"/"
- mdir(fo_outname)
- with open(fo_outname+cf[4], "wb") as fout:
- rom.seek(root+cf[0])
- fout.write(rom.read(cf[2]))
- rom.seek(root + sorted(entryque)[-1][0])
- rom.read(sorted(entryque)[-1][2])
- rom.seek(roundUp(rom.tell()), 1)
- elif check == 0x00010002:
- print("12QU at 0x{:X}".format(root))
- ONETWOFOLDER = OUT+"{:03d}_ONTW/".format(fidx)
- curf = ONETWOFOLDER
- mdir(curf)
- amo = getB(4)
- onetwoque = []
- for i in range(0,amo):
- _foname, sfindex, _finame, fadr, fsize = struct.unpack("<4s4s16sII", rom.read(0x20))
- try:
- foname = _foname.decode("utf-8").rstrip('\x00')
- except UnicodeDecodeError:
- foname = "{:08X}".format(struct.unpack("<I", _foname)[0])#str(_foname)
- try:
- finame = _finame.decode("utf-8").rstrip('\x00')
- except UnicodeDecodeError:
- finame = "{:08X}".format(struct.unpack("<I", _finame)[0])#str(_finame)
- try:
- sfindex = sfindex.decode("utf-8").rstrip('\x00')
- except UnicodeDecodeError:
- sfindex = "{:08X}".format(struct.unpack("<I", sfindex)[0])#str(_finame)
- if finame == " ":
- finame = "NONAME"
- estr = "{:8s} {:12s} {:08X}".format(foname,finame,findex)
- onetwoque.append([fadr, estr, fsize, foname, sfindex, finame])
- for ofile in range(0,len(onetwoque)):
- cf = onetwoque[ofile]
- fo_outname = curf+cf[3]+"/"
- mdir(fo_outname)
- fo_subname = fo_outname+cf[4]+"/"
- mdir(fo_subname)
- with open(fo_subname+cf[5], "wb") as fout:
- rom.seek(root+cf[0])
- fout.write(rom.read(cf[2]))
- rom.seek(root + sorted(onetwoque)[-1][0])
- rom.read(sorted(onetwoque)[-1][2])
- rom.seek(roundUp(rom.tell()), 1)
- elif check == 0xFFFF0001:
- rom.seek(-4,1)
- local_rta = rom.tell()
- print("FF01 at 0x{:X}".format(root))
- rest = 0x10
- while True:
- rom.read(1)
- rom.seek(roundUp(rom.tell()), 1)
- rom.seek(-rest,1)
- zcheck = sum(struct.unpack("<{:d}B".format(rest), rom.read(rest)))
- if zcheck == 0:
- print(" That's probably all... End at 0x{:X}".format(rom.tell()))
- new_rta = rom.tell()
- local_size = new_rta-local_rta
- rom.seek(local_rta)
- FF01FOLDER = OUT+"{:03d}_FF01/".format(fidx)
- mdir(FF01FOLDER)
- with open(FF01FOLDER+"FF01.bin", "wb") as ff01:
- ff01.write(rom.read(local_size))
- rom.seek(new_rta)
- break
- else:
- print(" ...")
- continue
- elif root == EMUEND:
- print("Emulated data at 0x{:X}".format(root))
- EMUFOLDER = OUT+"{:03d}_EMUD/".format(fidx)
- mdir(EMUFOLDER)
- with open(EMUFOLDER+"EMUD.bin", "wb") as emud:
- emud.write(rom.read(EMUSIZ))
- print(" done at 0x{:X}".format(rom.tell()))
- rom.seek(roundUp(rom.tell()), 1)
- print(" > 0x{:X}".format(rom.tell()))
- elif root == RGBEND:
- RGBFOLDER = OUT+"{:03d}_RGBD/".format(fidx)
- mdir(RGBFOLDER)
- for img in range(0, RGBAMO):
- print("RGB {:3d} at 0x{:X}".format(img, rom.tell()))
- canvas = Image.new("RGBA", (640,480))
- canvas.putdata(getRGB())
- canvas.save(RGBFOLDER+"{:03d}.png".format(img))
- break
- else:
- print("unknown check {:08X} at 0x{:08X}".format(check, root))
- print("1. Testing for ADPCM...")
- adpcm = testADPCM()
- if adpcm:
- pcmlist = getADPCMlist()
- rom.seek(roundUp(rom.tell()), 1)
- pcmroot = rom.tell()
- pcmcount = 0
- SOUNDFOLDER = OUT+"{:03d}_APCM/".format(fidx)
- mdir(SOUNDFOLDER)
- #with open(SOUNDFOLDER+"manifest.txt", "w") as pcm_manifest:
- # for snd in pcmlist:
- # with open(SOUNDFOLDER+"{:04d}.adpcm".format(pcmcount), "wb") as sout:
- # pcm_manifest.write("{:04d}.adpcm: {:d}Hz\n".format(pcmcount, RATELIST[snd["rate"]]))
- # rom.seek(pcmroot + snd["adr"])
- # sout.write(rom.read(snd["size"]))
- # pcmcount += 1
- with open(SOUNDFOLDER+"{:03d}.vca".format(fidx), "wb") as sout:
- rom.seek(root)
- sout.write(rom.read(pcmroot-root))
- with open(SOUNDFOLDER+"{:03d}.vcb".format(fidx), "wb") as sout:
- l = max(pcmlist, key=itemgetter('adr'))
- rom.seek(pcmroot + l["adr"])
- rom.read(l["size"])
- pcmend = rom.tell()
- rom.seek(pcmroot)
- sout.write(rom.read(pcmend-pcmroot))
- l = max(pcmlist, key=itemgetter('adr'))
- rom.seek(pcmroot + l["adr"])
- rom.read(l["size"])
- print("ADPCMs done at 0x{:X}".format(rom.tell()))
- rom.seek(roundUp(rom.tell()), 1)
- print(" continued to 0x{:X}".format(rom.tell()))
- else:
- print("idk. halt 0x{:08X}".format(root))
- #rom.read(4)
- #rom.seek(roundUp(rom.tell()), 1)
- break
- fidx += 1
- # X Y hw hg bytesz allocc
- #0200 0000 0190 00A3 0001FD60 00020000 / 512 0 400 163 130400 131072
- #0300 00A3 007A 0014 00001310 00001800 / 768 163 122 20 4880 6144
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement