def writeToRom(self, rom): self._ptrTbl.clear(32*40) destWriteLoc = 0xF0000 destRangeEnd = 0xF58EE # TODO Is this correct? Can we go more? destLocs = dict() emptyEntryPtr = EbModule.toSnesAddr(rom.writeToFree([0, 0])) pct = 45.0/(40*32) i=0 for entry in self._entries: if (entry == None) or (not entry): self._ptrTbl[i,0].setVal(emptyEntryPtr) else: entryLen = len(entry) writeLoc = rom.getFreeLoc(2 + entryLen*5) self._ptrTbl[i,0].setVal(EbModule.toSnesAddr(writeLoc)) rom[writeLoc] = entryLen & 0xff rom[writeLoc+1] = entryLen >> 8 writeLoc += 2 for door in entry: destWriteLoc += door.writeToRom(rom, writeLoc, destWriteLoc, destRangeEnd, destLocs) writeLoc += 5 i += 1 updateProgress(pct) self._ptrTbl.writeToRom(rom) # Mark any remaining space as free if destWriteLoc < destRangeEnd: rom.addFreeRanges([(destWriteLoc, destRangeEnd)]) updateProgress(5)
def writeToRom(self, rom): with EbCompressedData(self._gfx.sizeBlock()) as gb: self._gfx.writeToBlock(gb) EbModule.writeAsmPointer(rom, self._gfxPtrLoc, EbModule.toSnesAddr(gb.writeToFree(rom))) with EbCompressedData(self._arr.sizeBlock()) as ab: self._arr.writeToBlock(ab) EbModule.writeAsmPointer(rom, self._arrPtrLoc, EbModule.toSnesAddr(ab.writeToFree(rom))) with EbCompressedData(self._pals.sizeBlock()) as pb: self._pals.writeToBlock(pb) EbModule.writeAsmPointer(rom, self._palPtrLoc, EbModule.toSnesAddr(pb.writeToFree(rom)))
def writeToRom(self, rom): self._ptrTbl.clear(20) blockSize = 0 for entry in self._entries: for (flag, set) in entry: blockSize += 4 + 4*len(set) blockSize += 2 if blockSize > 0xffff: raise RuntimeError("Too many map changes") loc = rom.getFreeLoc(blockSize) rom[self._PTR_BANK_LOC] = (loc >> 16) + 0xc0 i = 0 for entry in self._entries: self._ptrTbl[i,0].setVal(loc & 0xffff) for (flag, set) in entry: rom.writeMulti(loc, flag, 2) rom.writeMulti(loc+2, len(set), 2) loc += 4 for (before, after) in set: rom.writeMulti(loc, before, 2) rom.writeMulti(loc+2, after, 2) loc += 4 rom[loc] = 0 rom[loc+1] = 0 loc += 2 i += 1 updateProgress(45.0/20) ptrTblLoc = self._ptrTbl.writeToFree(rom) rom.writeMulti(self._PTR_LOC, EbModule.toSnesAddr(ptrTblLoc), 3) updateProgress(5)
def writeToRom(self, rom): if self._data["Enable Skip"]: rom[0x1faae] = 0x5c loc = rom.getFreeLoc(10 + 4*5*5 + 3*6*5) rom.writeMulti(0x1faaf, EbModule.toSnesAddr(loc), 3) rom.write(loc, [0x48, 0x08, 0xe2, 0x20]) loc += 4 loc = self.writeLoaderAsm(rom, loc, self._data["Name1"], 5, 0xce, 0x99) loc = self.writeLoaderAsm(rom, loc, self._data["Name2"], 5, 0x2d, 0x9a) loc = self.writeLoaderAsm(rom, loc, self._data["Name3"], 5, 0x8c, 0x9a) loc = self.writeLoaderAsm(rom, loc, self._data["Name4"], 5, 0xeb, 0x9a) loc = self.writeLoaderAsm(rom, loc, self._data["Pet"], 6, 0x19, 0x98) loc = self.writeLoaderAsm(rom, loc, self._data["Food"], 6, 0x1f, 0x98) loc = self.writeLoaderAsm(rom, loc, self._data["Thing"], 6, 0x29, 0x98) if self._data["Enable Summary"]: rom.write(loc, [0x28, 0x68, 0x5c, 0xc0, 0xfa, 0xc1]) else: rom.write(loc, [0x28, 0x68, 0x5c, 0x05, 0xfd, 0xc1]) updateProgress(50)
def writeToRom(self, rom): numGroups = len(self._groups) self._grPtrTbl.clear(numGroups) with DataBlock(sum(map( lambda x: x.blockSize(), self._groups))) as block: loc = 0 i = 0 # Write all the groups to the block, and sprites to rom pct = 40.0 / numGroups for g in self._groups: g.writeSpritesToFree(rom) g.writeToBlock(block, loc) self._grPtrTbl[i,0].setVal(loc) loc += g.blockSize() i += 1 updateProgress(pct) # Write the block to rom and correct the group pointers addr = EbModule.toSnesAddr(block.writeToFree(rom)) for i in range(self._grPtrTbl.height()): self._grPtrTbl[i,0].setVal( self._grPtrTbl[i,0].val() + addr) # Write the pointer table self._grPtrTbl.writeToRom(rom) updateProgress(5) # Write the palettes self._grPalTbl.writeToRom(rom) updateProgress(5)
def writeSpritesToFree(self, rom): if self._numSprites == 0: self._spritePtrs = [] return spritePtrs = [ ] # Make a set of unique sprites uniqueSprites = [ ] for spf in self._sprites: sp = spf[0] try: spritePtrs.append((uniqueSprites.index(sp), False)) except ValueError: # Regular sprite not in uniques sp.hflip() try: spritePtrs.append((uniqueSprites.index(sp), True)) except ValueError: # Flipped sprite not in uniques uniqueSprites.append(sp) spritePtrs.append((uniqueSprites.index(sp), True)) # Find a free block loc = rom.getFreeLoc(sum(map(lambda x: x.blockSize(), uniqueSprites)),15) self._bank = EbModule.toSnesAddr(loc) >> 16 locStart = loc & 0xffff # Write each sprite uniqueSpriteAddrs = [ ] spBlockSize = uniqueSprites[0].blockSize() for uS in uniqueSprites: uS.writeToBlock(rom, loc) loc += spBlockSize # Output a list of pointers self._spritePtrs = map(lambda (n,f): (locStart + n*spBlockSize) | f, spritePtrs) for i in range(len(spritePtrs)): self._spritePtrs[i] |= (self._sprites[i][1]<<1)
def writeToRom(self, rom): self._mapEnemyTbl.writeToRom(rom) updateProgress(2.5) self._mapGroupPtrTbl.clear(len(self._mapGroups)) updateProgress(2.5) pct = 42.5 / len(self._mapGroups) i = 0 for (flag, rate1, rate2, subg1, subg2) in self._mapGroups: size = 4 if rate1 > 0: size += len(subg1) * 3 if rate2 > 0: size += len(subg2) * 3 loc = rom.getFreeLoc(size) self._mapGroupPtrTbl[i, 0].setVal(EbModule.toSnesAddr(loc)) rom.writeMulti(loc, flag, 2) rom[loc + 2] = rate1 rom[loc + 3] = rate2 loc += 4 for prob, egroup in subg1: rom[loc] = prob rom.writeMulti(loc + 1, egroup, 2) loc += 3 for prob, egroup in subg2: rom[loc] = prob rom.writeMulti(loc + 1, egroup, 2) loc += 3 i += 1 updateProgress(pct) self._mapGroupPtrTbl.writeToRom(rom) updateProgress(2.5)
def writeToRom(self, rom): pct = 40.0/(len(self._bsprites) + len(self._bsPals) + 3) # Write the main table self._enemyCfgTable.writeToRom(rom) updateProgress(pct) # Write the gfx ptr table self._bsPtrTbl.clear(len(self._bsprites)) i = 0 for bs in self._bsprites: with EbCompressedData(bs.sizeBlock()) as bsb: bs.writeToBlock(bsb) self._bsPtrTbl[i,0].setVal(EbModule.toSnesAddr( bsb.writeToFree(rom))) self._bsPtrTbl[i,1].setVal(bs.size()) i += 1 updateProgress(pct) gfxAddr = EbModule.toSnesAddr(self._bsPtrTbl.writeToFree(rom)) EbModule.writeAsmPointer(rom, self._ASMPTR_GFX, gfxAddr) updateProgress(pct) for p in self._REGPTR_GFX: rom.writeMulti(p, gfxAddr, 3) # Write the pal table self._bsPalsTable.clear(len(self._bsPals)) i = 0 for p in self._bsPals: self._bsPalsTable[i,0].setVal(p.getSubpal(0)) i += 1 updateProgress(pct) EbModule.writeAsmPointer(rom, self._ASMPTR_PAL, EbModule.toSnesAddr(self._bsPalsTable.writeToFree(rom))) updateProgress(pct) # Write the groups self._enemyGroupBgTbl.writeToRom(rom) updateProgress(5) i=0 for group in self._enemyGroups: loc = rom.getFreeLoc(len(group)*3 + 1) self._enemyGroupTbl[i,0].setVal(EbModule.toSnesAddr(loc)) i += 1 for enemyID, amount in group: rom[loc] = amount rom[loc+1] = enemyID & 0xff rom[loc+2] = enemyID >> 8 loc += 3 rom[loc] = 0xff self._enemyGroupTbl.writeToRom(rom) updateProgress(5)
def writeToRom(self, rom): # Arrangement space is 2048 bytes long since it's 32x32x2 in VRAM with EbCompressedData(self._pals.sizeBlock() + 2048 + self._gfx.sizeBlock()) as block: self._pals.writeToBlock(block, 0) self._arr.writeToBlock(block, 64) self._gfx.writeToBlock(block, 2048+64) newAddr = block.writeToFree(rom) rom.writeMulti(self._ptrLoc, EbModule.toSnesAddr(newAddr), 4)
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 writeToRom(self, rom): self._ptrTbl.clear(6) i = 0 for entry in self._entries: writeLoc = rom.getFreeLoc(len(entry)*5 + 1) self._ptrTbl[i,0].setVal( EbModule.toSnesAddr(writeLoc)) for (x, y, icon, flag) in entry: rom[writeLoc] = x rom[writeLoc+1] = y rom[writeLoc+2] = icon rom.writeMulti(writeLoc+3, flag, 2) writeLoc += 5 rom[writeLoc] = 0xff i += 1 updateProgress(45) EbModule.writeAsmPointer(rom, self._ASMPTR_PTR_TBL, EbModule.toSnesAddr( self._ptrTbl.writeToFree(rom))) 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 writeToRom(self, rom): for (t, a, asmPtrs, regPtrs, regPtrsOff) in self._tables: try: addr = EbModule.toSnesAddr(t.writeToFree(rom)) except Exception as inst: print t._name raise inst for asmPtr in asmPtrs: EbModule.writeAsmPointer(rom, asmPtr, addr) for regPtr in regPtrs: rom.writeMulti(regPtr, addr, 3) for (ptr, off) in regPtrsOff: rom.writeMulti(ptr, addr + off, 3) # Hardcoded number of entries in PSI Ability Table # if t._addr == 0xd58a50: # rom.writeMulti(0x1c843, t.height(), 2) updateProgress(self._pct)
def writeToRom(self, rom): self._bbgGfxPtrTbl.clear(len(self._bbgGfxArrs)) self._bbgArrPtrTbl.clear(len(self._bbgGfxArrs)) self._bbgPalPtrTbl.clear(len(self._bbgPals)) # Write gfx+arrs i = 0 pct = (50.0/3)/len(self._bbgGfxArrs) for (tg, a) in self._bbgGfxArrs: with EbCompressedData(tg.sizeBlock()) as tgb: tg.writeToBlock(tgb) self._bbgGfxPtrTbl[i,0].setVal(EbModule.toSnesAddr( tgb.writeToFree(rom))) with EbCompressedData(a.sizeBlock()) as ab: a.writeToBlock(ab) self._bbgArrPtrTbl[i,0].setVal(EbModule.toSnesAddr( ab.writeToFree(rom))) i += 1 updateProgress(pct) EbModule.writeAsmPointers(rom, self._ASMPTRS_GFX, EbModule.toSnesAddr(self._bbgGfxPtrTbl.writeToFree(rom))) EbModule.writeAsmPointers(rom, self._ASMPTRS_ARR, EbModule.toSnesAddr(self._bbgArrPtrTbl.writeToFree(rom))) # Write pals i = 0 pct = (50.0/3)/len(self._bbgPals) for p in self._bbgPals: with DataBlock(32) as pb: p.writeToBlock(pb) self._bbgPalPtrTbl[i,0].setVal(EbModule.toSnesAddr( pb.writeToFree(rom))) i += 1 updateProgress(pct) EbModule.writeAsmPointers(rom, self._ASMPTRS_PAL, EbModule.toSnesAddr(self._bbgPalPtrTbl.writeToFree(rom))) # Write the data table pct = (50.0/3)/3 self._bbgTbl.writeToRom(rom) updateProgress(pct) self._bbgScrollTbl.writeToRom(rom) updateProgress(pct) self._bbgDistorTbl.writeToRom(rom) updateProgress(pct)
def writeToRom(self, rom): self._ptrTbl.clear(165) writeLoc = 0xf58ef writeRangeEnd = 0xf61e5 # TODO Can re-use bank space from doors i=0 for entry in self._entries: entryLen = len(entry)*4 if writeLoc+entryLen > writeRangeEnd: raise RuntimeError("Not enough room for map music") self._ptrTbl[i,0].setVal(writeLoc & 0xffff) i += 1 for (flag, music) in entry: rom.writeMulti(writeLoc, flag, 2) rom[writeLoc+2] = music rom[writeLoc+3] = 0 writeLoc += 4 updateProgress(25) rom.writeMulti(self._ASMPTR, EbModule.toSnesAddr(self._ptrTbl.writeToFree(rom)), 3) if writeLoc < writeRangeEnd: rom.addFreeRanges([(writeLoc, writeRangeEnd)]) updateProgress(25)
def writeToRom(self, rom): self._ptrTbl.clear(32*40) writeLoc = 0xf61e7 writeRangeEnd = 0xf8984 i = 0 pct = 45.0/(40*32) for entry in self._entries: if (entry == None) or (not entry): self._ptrTbl[i,0].setVal(0) else: entryLen = len(entry) with DataBlock(2 + entryLen*4) as block: block[0] = entryLen & 0xff block[1] = entryLen >> 8 j = 2 for sprite in entry: block[j] = sprite.npcID & 0xff block[j+1] = sprite.npcID >> 8 block[j+2] = sprite.y block[j+3] = sprite.x j += 4 if writeLoc + len(block) > writeRangeEnd: # TODO Error, not enough space raise RuntimeError("Not enough map sprite space") else: block.writeToRom(rom, writeLoc) self._ptrTbl[i,0].setVal(writeLoc & 0xffff) writeLoc += len(block) updateProgress(pct) i += 1 loc = self._ptrTbl.writeToFree(rom) rom.writeMulti(self._PTR_LOC, EbModule.toSnesAddr(loc), 3) # Mark any remaining space as free if writeLoc < writeRangeEnd: rom.addFreeRanges([(writeLoc, writeRangeEnd)]) updateProgress(5)
def freeRanges(self): return map( lambda (x, a, b, c, d): (EbModule.toSnesAddr(x._addr), EbModule.toSnesAddr(x._addr) + x._size), self._tables )
def writeToRom(self, rom): for logo in self._logos: logo.writeToRom(rom) updateProgress(self._pct) for tmap in self._townmaps: tmap.writeToRom(rom) updateProgress(self._pct) with DataBlock(self._townmap_icons_pal.sizeBlock()) as b: self._townmap_icons_pal.writeToBlock(b) EbModule.writeAsmPointer(rom, self._ASMPTR_TOWN_MAP_ICON_PAL, EbModule.toSnesAddr(b.writeToFree(rom))) with EbCompressedData(self._townmap_icons.sizeBlock()) as cb: self._townmap_icons.writeToBlock(cb) EbModule.writeAsmPointer(rom, self._ASMPTR_TOWN_MAP_ICON_GFX, EbModule.toSnesAddr(cb.writeToFree(rom))) updateProgress(self._pct) with EbCompressedData(self._produced_pal.sizeBlock()) as cb: self._produced_pal.writeToBlock(cb) EbModule.writeAsmPointer(rom, self._ASMPTR_PRODUCED_PAL, EbModule.toSnesAddr(cb.writeToFree(rom))) with EbCompressedData(self._produced_gfx.sizeBlock()) as cb: self._produced_gfx.writeToBlock(cb) EbModule.writeAsmPointer(rom, self._ASMPTR_PRODUCED_GFX, EbModule.toSnesAddr(cb.writeToFree(rom))) with EbCompressedData(self._produced_arr.sizeBlock()) as cb: self._produced_arr.writeToBlock(cb) EbModule.writeAsmPointer(rom, self._ASMPTR_PRODUCED_ARR, EbModule.toSnesAddr(cb.writeToFree(rom))) updateProgress(self._pct) with EbCompressedData(self._presented_pal.sizeBlock()) as cb: self._presented_pal.writeToBlock(cb) EbModule.writeAsmPointer(rom, self._ASMPTR_PRESENTED_PAL, EbModule.toSnesAddr(cb.writeToFree(rom))) with EbCompressedData(self._presented_gfx.sizeBlock()) as cb: self._presented_gfx.writeToBlock(cb) EbModule.writeAsmPointer(rom, self._ASMPTR_PRESENTED_GFX, EbModule.toSnesAddr(cb.writeToFree(rom))) with EbCompressedData(self._presented_arr.sizeBlock()) as cb: self._presented_arr.writeToBlock(cb) EbModule.writeAsmPointer(rom, self._ASMPTR_PRESENTED_ARR, EbModule.toSnesAddr(cb.writeToFree(rom))) updateProgress(self._pct) with EbCompressedData(self._gas_gfx.sizeBlock()) as cb: self._gas_gfx.writeToBlock(cb) EbModule.writeAsmPointer(rom, self._ASMPTR_GAS_GFX, EbModule.toSnesAddr(cb.writeToFree(rom))) with EbCompressedData(self._gas_arr.sizeBlock()) as cb: self._gas_arr.writeToBlock(cb) EbModule.writeAsmPointer(rom, self._ASMPTR_GAS_ARR, EbModule.toSnesAddr(cb.writeToFree(rom))) with EbCompressedData(self._gas_pal1.sizeBlock()) as cb: self._gas_pal1.writeToBlock(cb) EbModule.writeAsmPointer(rom, self._ASMPTR_GAS_PAL1, EbModule.toSnesAddr(cb.writeToFree(rom))) with EbCompressedData(self._gas_pal2.sizeBlock()) as cb: self._gas_pal2.writeToBlock(cb) EbModule.writeAsmPointer(rom, self._ASMPTR_GAS_PAL2, EbModule.toSnesAddr(cb.writeToFree(rom))) with EbCompressedData(self._gas_pal3.sizeBlock()) as cb: self._gas_pal3.writeToBlock(cb) EbModule.writeAsmPointer(rom, self._ASMPTR_GAS_PAL3, EbModule.toSnesAddr(cb.writeToFree(rom))) updateProgress(self._pct)
def writeToRom(self, rom): numTsets = len(self._tsets) self._gfxPtrTbl.clear(numTsets) self._arrPtrTbl.clear(numTsets) self._colPtrTbl.clear(numTsets) self._mapTsetTbl.clear(32) self._palPtrTbl.clear(32) # Write gfx & arrs pct = 30.0/numTsets i=0 for tset in self._tsets: self._gfxPtrTbl[i,0].setVal(EbModule.toSnesAddr( tset.writeMinitilesToFree(rom))) self._arrPtrTbl[i,0].setVal(EbModule.toSnesAddr( tset.writeArrangementsToFree(rom))) i += 1 updateProgress(pct) self._gfxPtrTbl.writeToRom(rom) updateProgress(2) self._arrPtrTbl.writeToRom(rom) updateProgress(2) # Write collissions pct = 6.0/numTsets colLocs = dict() colWriteLoc = 0x180000 colRangeEnd = 0x18f05d i=0 for tset in self._tsets: with DataBlock(len(tset.col)*2) as colTable: j=0 for c in tset.col: hash = crc32(c) try: addr = colLocs[hash] except KeyError: if (colWriteLoc + 16) > colRangeEnd: # TODO Error, not enough space for collisions print "Ran out of collision space" raise Exception addr = 0 else: colLocs[hash] = colWriteLoc addr = colWriteLoc rom.write(colWriteLoc, c) colWriteLoc += 16 colTable[j] = addr & 0xff colTable[j+1] = (addr >> 8) & 0xff j += 2 self._colPtrTbl[i,0].setVal(EbModule.toSnesAddr( colTable.writeToFree(rom))) i += 1 updateProgress(pct) self._colPtrTbl.writeToRom(rom) updateProgress(1) # Write the palettes, they need to be in the DA bank pct = 7.0/32 palWriteLoc = 0x1a0000 palRangeEnd = 0x1afaa6 # can we go more? # Write maps/drawing tilesets associations and map tset pals for i in range(32): # For each map tileset # Find the drawing tileset number for this map tileset drawTset = -1 j = 0 for tset in self._tsets: for (mt,mp,pal) in tset.pals: if mt == i: drawTset = j break if drawTset != -1: break j += 1 else: # TODO Error, this drawing tileset isn't associated drawTset = 0 self._mapTsetTbl[i,0].setVal(drawTset) # Write the palette data for this map tileset mtset_pals = [(mp,pal) for (mt,mp,pal) in self._tsets[drawTset].pals if mt == i] mtset_pals.sort() # Let's take the easy way out and just write redundant flag pals # This will waste space but oh well # First, write the flag pals for (mp,pal) in mtset_pals: if pal.flag != 0: if palWriteLoc + 0xc0 > palRangeEnd: # TODO Error, not enough space for all these palettes raise RuntimeError("Too many palettes") pal.flagPal.writeToBlock(rom, palWriteLoc) pal.flagPalPtr = palWriteLoc & 0xffff palWriteLoc += 0xc0 self._palPtrTbl[i,0].setVal(EbModule.toSnesAddr(palWriteLoc)) # Now write the regular pals for (mp,pal) in mtset_pals: if palWriteLoc + 0xc0 > palRangeEnd: # TODO Error, not enough space for all these palettes raise RuntimeException("Too many palettes") pal.writeToBlock(rom, palWriteLoc) palWriteLoc += 0xc0 updateProgress(pct) self._mapTsetTbl.writeToRom(rom) updateProgress(1) self._palPtrTbl.writeToRom(rom) updateProgress(1) # Might as well use any extra leftover space ranges = [(colWriteLoc, colRangeEnd), (palWriteLoc, palRangeEnd)] ranges = [(a,b) for (a,b) in ranges if a < b] rom.addFreeRanges(ranges)