Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

more bugfixes

  • Loading branch information...
commit 4a1f702775d098d87e6678c980119832934e58bf 1 parent 6974813
kmeisthax authored
17 py/CodeModule/asm/commands.py
View
@@ -1,6 +1,7 @@
from CodeModule.cmd import command, logged, argument, group
from CodeModule.asm import asmotor, linker, writeout
from CodeModule.systems.helper import lookup_system_bases
+from CodeModule.exc import PEBKAC
@argument('infiles', nargs = '+', type=str, metavar='foo.o')
@argument('-f', type=str, metavar="asmotor", default = "asmotor", dest = "infmt")
@@ -16,12 +17,16 @@ def link(logger, infiles, infmt, outfiles, baserom, platform, **kwargs):
logger.critical("Only ASMotor format objects are currently supported.")
return
- logger.info("Begin %(fmt)s linking operation with %(platform)r..." % {"fmt":fmt, "platform":platform})
+ platforms = []
- bases = ["linker", fmt]
- bases.extend(platform)
+ for platformcnk in platform:
+ platforms.extend(platformcnk.split(","))
- platcls = type("platcls", {}, lookup_system_bases(bases))
+ logdata = {"infmt":infmt, "platform":platforms}
+
+ logger.info("Begin %(infmt)s linking operation with %(platform)r..." % logdata)
+
+ platcls = type("platcls", lookup_system_bases(platforms), {})
plat = platcls()
lnk = asmotor.ASMotorLinker(plat)
@@ -35,7 +40,9 @@ def link(logger, infiles, infmt, outfiles, baserom, platform, **kwargs):
else:
wotgt = writeout.ROMWriteout(streams = {"ROM":outfiles}, platform = plat)
- logger.info("Loading %(lenfname)d files..." % {"lenfname":len(infiles)})
+ logdata["lenfname"] = len(infiles)
+
+ logger.info("Loading %(lenfname)d files..." % logdata)
for fname in infiles:
lnk.loadTranslationUnit(fname)
23 py/CodeModule/asm/linker.py
View
@@ -47,7 +47,8 @@
list of all assembled locations."""
import bisect, heapq
-from CodeModule.exc import FixationConflict, OutOfSegmentSpace
+from CodeModule.exc import FixationConflict, OutOfSegmentSpace, PEBKAC
+from CodeModule.cmd import logged
from collections import namedtuple
class Fixator(object):
@@ -384,13 +385,22 @@ def __init__(self, *args):
class Linker(object):
MemGroup = namedtuple("MemGroup", ["fixator", "sections"])
- def __init__(self, platform):
+ @logged("linker", logcalls=True)
+ def __init__(logger, self, platform):
self.groups = {}
self.resolver = Resolver()
self.platform = platform
for marea in self.platform.MEMAREAS:
spec = self.platform.__getattribute__(marea)
+
+ if "shadows" in spec.keys():
+ continue #we don't care
+
+ logdata = {"marea":marea, "spec":spec}
+ logger.debug("Setting up memory area %(marea)s." % logdata)
+ logger.debug("Spec: %(spec)r" % logdata)
+
staticSize = spec["segsize"]
segCount = spec["maxsegs"]
@@ -400,12 +410,19 @@ def __init__(self, platform):
segids.append(i)
baseAddr = 0
for view in spec["views"]:
- if type(view[1]) is int and view[1] is i:
+ if type(view[1]) is int:
+ if view[1] is i:
+ baseAddr = view[0]
+ break
+ elif view[1] is None:
baseAddr = view[0]
break
elif i >= view[1][0] and i <= view[1][1]:
baseAddr = view[0]
break
+ else:
+ logger.error("Memory Area has an unmapped segment!")
+ raise PEBKAC
segsize[i] = (baseAddr, baseAddr+staticSize)
5 py/CodeModule/asm/writeout.py
View
@@ -17,7 +17,7 @@ def __init__(self, streams, platform, *args, **kwargs):
self.streamName = None
self.streamSpec = None
- super(Writeout, self).__init__(streams, platform, *args, **kwargs)
+ super(ROMWriteout, self).__init__(*args, **kwargs)
def beginWrite(self, linkerobj):
self.linkerobj = linkerobj
@@ -53,7 +53,7 @@ class OverlayWriteout(ROMWriteout):
"""A Writeout object that overlays new streams over an existing base ROM."""
def __init__(self, bases, *args, **kwargs):
self.bases = bases
- super(Writeout, self).__init__(bases, *args, **kwargs)
+ super(OverlayWriteout, self).__init__(*args, **kwargs)
def enterStream(self, streamName, streamSpec):
#just-in-time copy from base ROM to output
@@ -85,6 +85,7 @@ def __init__(self, mapstream, platform, *args, **kwargs):
self.mapstream = mapstream
self.platform = platform
self.linkerobj = None
+ super(MapWriteout, self).__init__(*args, **kwargs)
def beginWrite(self, linkerobj):
self.linkerobj = linkerobj
36 py/CodeModule/cmd.py
View
@@ -1,8 +1,12 @@
import argparse, sys, logging
parser = argparse.ArgumentParser(description="Low-level programming/hacking framework")
+parser.add_argument("--loglv", default="INFO")
subparser = parser.add_subparsers()
+def global_options(loglv="NOTSET", **kwargs):
+ logging.getLogger("").setLevel(loglv)
+
class commandcls(object):
def __init__(self, wrapped):
self.__func = wrapped
@@ -18,7 +22,11 @@ def __init__(self, wrapped):
self.__curgroup = None
def __call__(self, resp, *args, **kwargs):
- kwargs.update(vars(resp))
+ rkwargs = vars(resp)
+
+ global_options(**rkwargs)
+ kwargs.update(rkwargs)
+
self.__func(*args, **kwargs)
def command(func):
@@ -40,16 +48,9 @@ def decorum(self):
return self
return decorum
-def main(argv = sys.argv):
- #for right now, just import everything we know has commands
- #in the future, add some import machinery magic to import everything named "commands"
- import CodeModule.asm.commands
- resp = parser.parse_args(argv[1:])
- resp.func(resp)
-
-logging.basicConfig(format = "[%(asctime)-15s|%(levelno)s|%(name)s|%(filename)s:%(lineno)d] %(message)s")
+logging.basicConfig(format = "[%(relativeCreated)12d|%(levelname)-4.4s|%(name)-4.4s|%(filename)s:%(lineno)d] %(message)s")
-def logged(loggername = None, logcalls = False, calllvl = logging.INFO, logexcept = True, exceptlvl = logging.FATAL, logsuccess = False, successlvl = logging.DEBUG):
+def logged(loggername = None, logcalls = False, calllvl = logging.DEBUG, logexcept = True, exceptlvl = logging.FATAL, catchexcept = False, logsuccess = False, successlvl = logging.DEBUG):
def loggedifier(innerfunc):
ologger = logging.getLogger(loggername)
@@ -63,10 +64,14 @@ def outerfunc(*args, **kwargs):
"%(ifname)s called with args: %(args)r and keyword args: %(kwargs)r" % logdata)
try:
- retval = innerfunc(logger = ologger, *args, **kwargs)
+ retval = innerfunc(ologger, *args, **kwargs)
except Exception as e:
if logexcept:
- ologger.log(exceptlvl, "%(ifname)s raised an exception!" % logdata, exc_info = True)
+ ologger.log(exceptlvl, "%(ifname)s raised an exception!" % logdata)
+ ologger.log(exceptlvl, "Called with args %(args)r and kwargs %(kwargs)r." % logdata, exc_info = True)
+
+ if not catchexcept:
+ raise e
else:
logdata["retval"] = retval
@@ -78,3 +83,10 @@ def outerfunc(*args, **kwargs):
outerfunc.__name__ = innerfunc.__name__
return outerfunc
return loggedifier
+
+def main(argv = sys.argv):
+ #for right now, just import everything we know has commands
+ #in the future, add some import machinery magic to import everything named "commands"
+ import CodeModule.asm.commands
+ resp = parser.parse_args(argv[1:])
+ resp.func(resp)
21 py/CodeModule/systems/gb.py
View
@@ -32,7 +32,7 @@ class MBC1Mapper(BasePlatform):
"unusable":[(None, 0x20), (None, 0x40), (None, 0x60)],
"type":linker.PermenantArea}
SRAM = {"segsize":0x2000,
- "views":[(0xA000, 0x03)],
+ "views":[(0xA000, None)],
"maxsegs":4,
"type":linker.PermenantArea}
@@ -90,7 +90,7 @@ class MBC3Mapper(BasePlatform):
"maxsegs":0x80,
"type":linker.PermenantArea}
SRAM = {"segsize":0x2000,
- "views":[(0xA000, 0x03)],
+ "views":[(0xA000, None)],
"maxsegs":4,
"type":linker.PermenantArea}
@@ -117,7 +117,7 @@ class MBC5Mapper(BasePlatform):
"maxsegs":0x200,
"type":linker.PermenantArea}
SRAM = {"segsize":0x2000,
- "views":[(0xA000, 0x10)],
+ "views":[(0xA000, None)],
"maxsegs":0x10,
"type":linker.PermenantArea}
@@ -187,8 +187,8 @@ class CGB(BaseSystem):
"views":[(0xC000, 0), (0xD000, (1, 0x8))],
"maxsegs":8,
"type":linker.DynamicArea}
- VRAM = {"segsize":0x1000,
- "views":[(0x8000, 0), (0x9000, (1, 0x8))],
+ VRAM = {"segsize":0x2000,
+ "views":[(0x8000, None)],
"maxsegs":2,
"type":linker.DynamicArea}
@@ -226,7 +226,16 @@ def banked2flat(bank, addr):
else:
return super(BaseSystem, self).banked2flat(bank, addr)
-VARIANTLIST = ({"DMG":DMG, "CGB":CGB}, {"Flat":FlatMapper, "MBC1":MBC1Mapper, "MBC2":MBC2Mapper, "MBC3":MBC3Mapper, "MBC5":MBC5Mapper})
+MAPPERLIST = {"flat":(FlatMapper, None),
+ "mbc1":(MBC1Mapper, None),
+ "mbc2":(MBC2Mapper, None),
+ "mbc3":(MBC3Mapper, None),
+ "mbc5":(MBC5Mapper, None)}
+
+VARIANTLIST = {"dmg":(DMG, MAPPERLIST),
+ "gb":(DMG, MAPPERLIST),
+ "cgb":(CGB, MAPPERLIST),
+ "gbc":(CGB, MAPPERLIST)}
def GameboyLinker(variant1, variant2):
class GameboyLinkerInstance(linker.Linker, variant1, variant2):
50 py/CodeModule/systems/helper.py
View
@@ -6,32 +6,44 @@ def flat2banked(self, addr, src):
return (0, 0)
from CodeModule.systems.gb import VARIANTLIST as GBVariantList
+from CodeModule.cmd import logged
from CodeModule.asm import asmotor, linker
from CodeModule.exc import PEBKAC
-VARIANTLIST = []
-VARIANTLIST.extend(GBVariantList)
+#The variant list is structured as a tree of dictionaries.
+#Each dictionary has platform names as keys and tuples of (Base, ChildNode) as values.
+#The Base is a class base object, ChildNode is another dictionary or None.
+#If ChildNode isn't None, then it is another variant dictionary which must be indexed
+#to get another base.
+VARIANTLIST = {}
+VARIANTLIST.update(GBVariantList)
-def lookup_system_bases(basenames):
- """Given a list of platform attributes, return a set of bases to construct a class with.
+@logged("pfrm")
+def lookup_system_bases(logger, exbn):
+ """Given a list of platform attributes, return tuple of bases to construct a class with."""
- The list of bases is usually a triplet of object code format, system, and
- cartridge mapper chip."""
+ #shallow copy the basename list
+ basenames = []
+ for bn in exbn:
+ basenames.append(bn)
bases = []
- usedvariants = []
+ next_vlist = VARIANTLIST
- for basename in basenames:
- for variant in VARIANTLIST:
- if variant in usedvariants:
- continue
-
- if basename in variant.keys():
- bases.append(variant[basename])
- usedvariants.append(variant)
- break
- else:
- #can't find the variant class
+ while next_vlist != None:
+ cur_bn = None
+
+ for basename in basenames:
+ if basename in next_vlist.keys():
+ bases.append(next_vlist[basename][0])
+ next_vlist = next_vlist[basename][1]
+ cur_bn = basename
+
+ if cur_bn is None:
+ logger.error("No matching platform base in %(basenames)s" % {"basenames":basenames})
raise PEBKAC
+
+ basenames.remove(cur_bn)
- return bases
+ logger.debug(repr(bases))
+ return tuple(bases)
Please sign in to comment.
Something went wrong with that request. Please try again.