def readFromRom(self, rom): self._bbgTbl.readFromRom(rom) pct = 50.0/(6+self._bbgTbl.height()) self._bbgGfxPtrTbl.readFromRom(rom, EbModule.toRegAddr(EbModule.readAsmPointer(rom, self._ASMPTRS_GFX[0]))) updateProgress(pct) self._bbgArrPtrTbl.readFromRom(rom, EbModule.toRegAddr(EbModule.readAsmPointer(rom, self._ASMPTRS_ARR[0]))) updateProgress(pct) self._bbgPalPtrTbl.readFromRom(rom, EbModule.toRegAddr(EbModule.readAsmPointer(rom, self._ASMPTRS_PAL[0]))) updateProgress(pct) self._bbgGfxArrs = [ None for i in range(self._bbgGfxPtrTbl.height()) ] self._bbgPals = [ None for i in range(self._bbgPalPtrTbl.height()) ] updateProgress(pct) self._bbgScrollTbl.readFromRom(rom) updateProgress(pct) self._bbgDistorTbl.readFromRom(rom) updateProgress(pct) for i in range(self._bbgTbl.height()): gfxNum = self._bbgTbl[i,0].val() colorDepth = self._bbgTbl[i,2].val() if (self._bbgGfxArrs[gfxNum] == None): # Max size used in rom: 421 (2bpp) 442 (4bpp) tg = EbTileGraphics(512, 8, colorDepth) with EbCompressedData() as tgb: tgb.readFromRom(rom, EbModule.toRegAddr( self._bbgGfxPtrTbl[gfxNum,0].val())) tg.readFromBlock(tgb) a = EbArrangement(32, 32) with EbCompressedData() as ab: ab.readFromRom(rom, EbModule.toRegAddr( self._bbgArrPtrTbl[gfxNum,0].val())) a.readFromBlock(ab) self._bbgGfxArrs[gfxNum] = (tg, a) palNum = self._bbgTbl[i,1].val() if (self._bbgPals[palNum] == None): with DataBlock(32) as pb: pb.readFromRom(rom, EbModule.toRegAddr(self._bbgPalPtrTbl[palNum,0].val())) p = EbPalettes(1, 16) p.readFromBlock(pb) self._bbgPals[palNum] = p updateProgress(pct)
class WindowGraphicsModule(EbModule.EbModule): _name = "Window Graphics" _ASMPTR_1 = 0x47c47 _ASMPTR_2 = 0x47caa _ASMPTRS_NAMES = [0x1F70F, 0x1F72A, 0x1F745, 0x1F760, 0x1F77B] _PREVIEW_SUBPALS = [0, 0, 0, 0, 1, 1, 1, 4, 4, 4, 4, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 6, 6, 6, 6, 3, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 3, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 1, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 1, 0, 0 ] def __init__(self): self._gfx1 = EbTileGraphics(416, 8, 2) self._gfx2 = EbTileGraphics(7, 8, 2) self._flavPals = [EbPalettes(8,4) for i in range(7)] self._flavNames = [(i,TextTableEntry(None, 25)) for i in self._ASMPTRS_NAMES] def freeRanges(self): return [(0x200000, 0x20079f)] # Graphics def readFromRom(self, rom): with EbCompressedData() as tgb1: tgb1.readFromRom(rom, EbModule.toRegAddr( EbModule.readAsmPointer(rom, self._ASMPTR_1))) self._gfx1.readFromBlock(tgb1) updateProgress(20) with EbCompressedData() as tgb2: tgb2.readFromRom(rom, EbModule.toRegAddr( EbModule.readAsmPointer(rom, self._ASMPTR_2))) self._gfx2.readFromBlock(tgb2) updateProgress(20) # Read palettes loc = 0x201fc8 for pal in self._flavPals: pal.readFromBlock(rom, loc=loc) loc += 64 updateProgress(5) # Read names for ptr, field in self._flavNames: field.readFromRom(rom, EbModule.toRegAddr( EbModule.readAsmPointer(rom, ptr))) updateProgress(5) def writeToRom(self, rom): with EbCompressedData(self._gfx1.sizeBlock()) as gb: self._gfx1.writeToBlock(gb) EbModule.writeAsmPointer(rom, self._ASMPTR_1, EbModule.toSnesAddr(gb.writeToFree(rom))) updateProgress(20) with EbCompressedData(self._gfx2.sizeBlock()) as gb: self._gfx2.writeToBlock(gb) EbModule.writeAsmPointer(rom, self._ASMPTR_2, EbModule.toSnesAddr(gb.writeToFree(rom))) updateProgress(20) # Write pals loc = 0x201fc8 for pal in self._flavPals: pal.writeToBlock(rom, loc=loc) loc += 64 updateProgress(5) # Write names for ptr, field in self._flavNames: loc = EbModule.toSnesAddr(field.writeToFree(rom)) EbModule.writeAsmPointer(rom, ptr, loc) updateProgress(5) def writeToProject(self, resourceOpener): arr1 = EbArrangement(16, 26) for i in range(416): arr1[i%16,i/16] = (False, False, False, self._PREVIEW_SUBPALS[i], i) i = 0 for pal in self._flavPals: with resourceOpener("WindowGraphics/Windows1_" + str(i), "png") as imgFile: img1 = arr1.toImage(self._gfx1, pal) img1.save(imgFile, "png") with resourceOpener("WindowGraphics/Windows2_" + str(i), "png") as imgFile: img2 = self._gfx2.dumpToImage(pal.getSubpal(7), width=7) img2.save(imgFile, "png") i += 1 updateProgress(40) # Write names with resourceOpener("WindowGraphics/flavor_names", "txt") as f: for ptr, field in self._flavNames: print >>f, field.dump() updateProgress(10) def readFromProject(self, resourceOpener): # Read graphics. Just use the first of each image. with resourceOpener("WindowGraphics/Windows1_0", "png") as imgFile: img = Image.open(imgFile) if img.mode != 'P': raise RuntimeError("WindowGraphics/Windows1_0 is not an indexed PNG.") self._gfx1.loadFromImage(img) updateProgress(20) with resourceOpener("WindowGraphics/Windows2_0", "png") as imgFile: img = Image.open(imgFile) if img.mode != 'P': raise RuntimeError("WindowGraphics/Windows2_0 is not an indexed PNG.") self._gfx2.loadFromImage(img) updateProgress(20) # Read pals from Windows1 of each flavor. # Read subpal 7 from Windows2 of each flavor. i = 0 for pal in self._flavPals: # Read all the palette data from Windows1 with resourceOpener("WindowGraphics/Windows1_" + str(i), "png") as imgFile: img = Image.open(imgFile) if img.mode != 'P': raise RuntimeError("WindowGraphics/Windows1_" + str(i) + " is not an indexed PNG.") palData = img.getpalette() m=0 for j in range(8): for k in range(4): pal[j,k] = (palData[m], palData[m+1], palData[m+2]) m += 3 # Overwrite subpalette 7 from the palette of Windows2 with resourceOpener("WindowGraphics/Windows2_" + str(i), "png") as imgFile: img = Image.open(imgFile) if img.mode != 'P': raise RuntimeError("WindowGraphics/Windows2_" + str(i) + " is not an indexed PNG.") palData = img.getpalette() m=0 for k in range(4): pal[7,k] = (palData[m], palData[m+1], palData[m+2]) m += 3 i += 1 updateProgress(5) # Read names with resourceOpener("WindowGraphics/flavor_names", "txt") as f: for ptr, field in self._flavNames: field.load(f.readline()[:-1]) updateProgress(5)
class FontModule(EbModule.EbModule): _name = "Fonts" _CREDITS_PREVIEW_SUBPALS = [ 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] _ASMPTR_CREDITS_GFX = 0x4f1a7 _ADDR_CREDITS_PAL = 0x21e914 def __init__(self): self._fonts = [ Font(0x210cda, 0x210c7a, 16, 16), Font(0x2013b9, 0x201359, 16, 16), Font(0x2122fa, 0x21229a, 16, 16), Font(0x21193a, 0x2118da, 8, 16), Font(0x211f9a, 0x211f3a, 8, 8) ] self._cfont = EbTileGraphics(192, 8, 2) self._cpal = EbPalettes(2, 4) self._pct = 50.0/(len(self._fonts)+1) def freeRanges(self): return [(0x21e528, 0x21e913)] # Credits font graphics def readCreditsFontFromRom(self, rom): self._cpal.readFromBlock(rom, loc=self._ADDR_CREDITS_PAL) with EbCompressedData() as cb: cb.readFromRom(rom, EbModule.toRegAddr( EbModule.readAsmPointer( rom, self._ASMPTR_CREDITS_GFX))) self._cfont.readFromBlock(cb) def readFromRom(self, rom): for f in self._fonts: f.readFromRom(rom) updateProgress(self._pct) self.readCreditsFontFromRom(rom) updateProgress(self._pct) def writeToRom(self, rom): for f in self._fonts: f.writeToRom(rom) updateProgress(self._pct) self._cpal.writeToBlock(rom, loc=self._ADDR_CREDITS_PAL) with EbCompressedData(self._cfont.sizeBlock()) as cb: self._cfont.writeToBlock(cb) EbModule.writeAsmPointer(rom, self._ASMPTR_CREDITS_GFX, EbModule.toSnesAddr(cb.writeToFree(rom))) updateProgress(self._pct) def writeCreditsFontToProject(self, resourceOpener): arr = EbArrangement(16, 12) for i in range(192): arr[i%16, i/16] = (False, False, False, self._CREDITS_PREVIEW_SUBPALS[i], i) img = arr.toImage(self._cfont, self._cpal) with resourceOpener("Fonts/credits", "png") as imgFile: img.save(imgFile, "png") imgFile.close() def writeToProject(self, resourceOpener): out = dict() i=0 for font in self._fonts: # Write the PNG img = font.toImage() with resourceOpener("Fonts/" + str(i), 'png') as imgFile: img.save(imgFile, 'png') # Write the widths out = font.dumpWidths() with resourceOpener("Fonts/" + str(i) + "_widths", "yml") as f: yaml.dump(out, f, default_flow_style=False, Dumper=yaml.CSafeDumper) i += 1 updateProgress(self._pct) self.writeCreditsFontToProject(resourceOpener) updateProgress(self._pct) def readFromProject(self, resourceOpener): i = 0 for font in self._fonts: with resourceOpener("Fonts/" + str(i), "png") as imgFile: img = Image.open(imgFile) if img.mode != 'P': raise RuntimeError("Fonts/" + str(i) + " is not an indexed PNG.") font.fromImage(img) with resourceOpener("Fonts/" + str(i) + "_widths", "yml") as f: input = yaml.load(f, Loader=yaml.CSafeLoader) font.loadWidths(input) i += 1 updateProgress(self._pct) with resourceOpener("Fonts/credits", "png") as imgFile: img = Image.open(imgFile) if img.mode != 'P': raise RuntimeError("Fonts/credits is not an indexed PNG.") self._cfont.loadFromImage(img) self._cpal.loadFromImage(img) updateProgress(self._pct) def upgradeProject(self, oldVersion, newVersion, rom, resourceOpenerR, resourceOpenerW): if oldVersion == newVersion: updateProgress(100) return elif oldVersion <= 2: self.readCreditsFontFromRom(rom) self.writeCreditsFontToProject(resourceOpenerW) self.upgradeProject(3, newVersion, rom, resourceOpenerR, resourceOpenerW) else: self.upgradeProject(oldVersion+1, newVersion, rom, resourceOpenerR, resourceOpenerW)
class Tileset: def __init__(self): self.tg = EbTileGraphics(896, 8, 4) self.tg._tiles = [ None ] * 896 self.arr = [None for i in range(0,1024)] self.col = [None for i in range(0,1024)] self.pals = [ ] def readMinitilesFromRom(self, rom, addr): with EbCompressedData() as tgb: tgb.readFromRom(rom, addr) self.tg.readFromBlock(tgb) def writeMinitilesToFree(self, rom): with EbCompressedData(self.tg.sizeBlock()) as tgb: self.tg.writeToBlock(tgb) return tgb.writeToFree(rom) def readArrangementsFromRom(self, rom, addr): with EbCompressedData() as ab: ab.readFromRom(rom, addr) self.numArrs = len(ab)/32 a = 0 for i in range(self.numArrs): self.arr[i] = [ [0 for y in range(4)] for z in range(4) ] for j in range(4): for k in range(4): self.arr[i][k][j] = ab[a] + (ab[a+1]<<8) a += 2 def writeArrangementsToFree(self, rom): with EbCompressedData(1024*16*2) as ab: i=0 for a in self.arr: for j in range(4): for k in range(4): ab[i] = a[k][j] & 0xff ab[i+1] = a[k][j] >> 8 i += 2 return ab.writeToFree(rom) def readCollisionsFromRom(self, rom, addr): for i in range(self.numArrs): tmp = rom.readMulti(addr + i*2, 2) self.col[i] = rom[0x180000+tmp:0x180000+tmp+16] def readPaletteFromRom(self, rom, mapTset, palNum, addr): pal = MapPalette() pal.readFromRom(rom, addr) self.pals.append((mapTset, palNum, pal)) def getTileAsString(self, n): if n >= 896: return "0000000000000000000000000000000000000000000000000000000000000000" else: s = str() t = self.tg[n] for j in xrange(8): for i in xrange(8): s += chars[t[i][j]] return s def setTileFromString(self, n, s): if n < 896: strVals = map(lambda x: int(x,32), s) k=0 tile = [array('B', [0]*8) for i in xrange(8)] for j in xrange(8): for i in xrange(8): tile[i][j] = strVals[k] k += 1 self.tg._tiles[n] = tile def getArrAsString(self, n): if n >= self.numArrs: return '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' else: s = str() tmp = 0 for j in xrange(4): for k in xrange(4): s += hex(self.arr[n][k][j])[2:].zfill(4) s += hex(self.col[n][j*4+k])[2:].zfill(2) return s def setArrFromString(self, n, s): i=0 self.arr[n] = [ [0 for y in range(4)] for z in range(4) ] self.col[n] = array('B', [0]*16) for j in xrange(4): for k in xrange(4): self.arr[n][k][j] = int(s[i:i+4], 16) self.col[n][j*4+k] = int(s[i+4:i+6], 16) i += 6 def writeToFTS(self, file): for i in range(512): print >>file, self.getTileAsString(i) print >>file, self.getTileAsString(i^512) print >>file print >>file for (mt,mp,pal) in self.pals: file.write(chars[mt]) file.write(chars[mp]) print >>file, pal.getAsString() print >>file print >>file for i in range(1024): print >>file, self.getArrAsString(i) def hasMapTileset(self, mt): for (mt2,mp,pal) in self.pals: if mt == mt2: return True return False def readFromFTS(self, file): for i in range(512): self.setTileFromString(i, file.readline()[:-1]) self.setTileFromString(i^512, file.readline()[:-1]) file.readline() file.readline() while True: line = file.readline() if line == "\n": break mt = int(line[0], 32) mp = int(line[1], 32) pal = MapPalette() pal.setFromString(line[2:-1]) self.pals.append((mt,mp,pal)) file.readline() for i in range(1024): self.setArrFromString(i, file.readline()[:-1])