mirror of
https://github.com/robmcmullen/asmgen.git
synced 2024-06-08 22:29:39 +00:00
Added processor and assembler syntax options
* added complete lookup table generation
This commit is contained in:
parent
d02300573d
commit
3afe35febe
176
HiSprite.py
176
HiSprite.py
|
@ -56,13 +56,47 @@ def slugify(s):
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
class Syntax(object):
|
||||||
|
def asm(self, text):
|
||||||
|
return "\t%s" % text
|
||||||
|
|
||||||
|
def comment(self, text):
|
||||||
|
return "\t; %s" % text
|
||||||
|
|
||||||
|
def label(self, text):
|
||||||
|
return text
|
||||||
|
|
||||||
|
def byte(self, text):
|
||||||
|
return self.asm(".byte %s" % text)
|
||||||
|
|
||||||
|
def word(self, text):
|
||||||
|
return self.asm(".word %s" % text)
|
||||||
|
|
||||||
|
def address(self, text):
|
||||||
|
return self.asm(".addr %s" % text)
|
||||||
|
|
||||||
|
def origin(self, text):
|
||||||
|
return self.asm("*= %s" % text)
|
||||||
|
|
||||||
|
|
||||||
|
class Mac65(Syntax):
|
||||||
|
def address(self, text):
|
||||||
|
return self.asm(".word %s" % text)
|
||||||
|
|
||||||
|
|
||||||
|
class CC65(Syntax):
|
||||||
|
def label(self, text):
|
||||||
|
return "%s:" % text
|
||||||
|
|
||||||
|
|
||||||
class Listing(object):
|
class Listing(object):
|
||||||
disclaimer = '''
|
disclaimer = '''
|
||||||
; This file was generated by HiSprite.py, a sprite compiler by Quinn Dunki.
|
; This file was generated by HiSprite.py, a sprite compiler by Quinn Dunki.
|
||||||
; If you feel the need to modify this file, you are probably doing it wrong.
|
; If you feel the need to modify this file, you are probably doing it wrong.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, assembler):
|
||||||
|
self.assembler = assembler
|
||||||
self.lines = [self.disclaimer]
|
self.lines = [self.disclaimer]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -71,10 +105,31 @@ class Listing(object):
|
||||||
def out(self, line):
|
def out(self, line):
|
||||||
self.lines.append(line)
|
self.lines.append(line)
|
||||||
|
|
||||||
|
def out_append_last(self, line):
|
||||||
|
self.lines[-1] += line
|
||||||
|
|
||||||
|
def label(self, text):
|
||||||
|
self.out(self.assembler.label(text))
|
||||||
|
|
||||||
|
def comment(self, text):
|
||||||
|
self.out_append_last(self.assembler.comment(text))
|
||||||
|
|
||||||
|
def asm(self, text):
|
||||||
|
self.out(self.assembler.asm(text))
|
||||||
|
|
||||||
|
def addr(self, text):
|
||||||
|
self.out(self.assembler.address(text))
|
||||||
|
|
||||||
|
def byte(self, text):
|
||||||
|
self.out(self.assembler.byte(text))
|
||||||
|
|
||||||
|
def word(self, text):
|
||||||
|
self.out(self.assembler.word(text))
|
||||||
|
|
||||||
|
|
||||||
class Sprite(Listing):
|
class Sprite(Listing):
|
||||||
def __init__(self, pngfile, xdraw=False):
|
def __init__(self, pngfile, assembler, xdraw=False, processor="any"):
|
||||||
Listing.__init__(self)
|
Listing.__init__(self, assembler)
|
||||||
|
|
||||||
reader = png.Reader(pngfile)
|
reader = png.Reader(pngfile)
|
||||||
try:
|
try:
|
||||||
|
@ -83,6 +138,7 @@ class Sprite(Listing):
|
||||||
raise RuntimeError
|
raise RuntimeError
|
||||||
|
|
||||||
self.xdraw = xdraw
|
self.xdraw = xdraw
|
||||||
|
self.processor = processor
|
||||||
self.niceName = slugify(os.path.splitext(pngfile)[0])
|
self.niceName = slugify(os.path.splitext(pngfile)[0])
|
||||||
self.width = pngdata[0]
|
self.width = pngdata[0]
|
||||||
self.height = pngdata[1]
|
self.height = pngdata[1]
|
||||||
|
@ -98,32 +154,46 @@ class Sprite(Listing):
|
||||||
|
|
||||||
def jumpTable(self):
|
def jumpTable(self):
|
||||||
# Prologue
|
# Prologue
|
||||||
self.out("%s: ;%d bytes per row" % (self.niceName, self.byteWidth))
|
self.label("%s" % self.niceName)
|
||||||
self.out("\tSAVE_AXY")
|
self.comment("%d bytes per row" % self.byteWidth)
|
||||||
self.out("\tldy PARAM0")
|
self.asm("SAVE_AXY")
|
||||||
self.out("\tldx MOD7_2,y")
|
self.asm("ldy PARAM0")
|
||||||
self.out(".ifpC02")
|
self.asm("ldx MOD7_2,y")
|
||||||
self.out("\tjmp (%s_JMP,x)\n" % (self.niceName))
|
|
||||||
|
if self.processor == "any":
|
||||||
|
self.out(".ifpC02")
|
||||||
|
self.jump65C02()
|
||||||
|
self.out(".else")
|
||||||
|
self.jump6502()
|
||||||
|
self.out(".endif")
|
||||||
|
elif self.processor == "65C02":
|
||||||
|
self.jump65C02()
|
||||||
|
elif self.processor == "6502":
|
||||||
|
self.jump6502()
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Processor %s not supported" % self.processor)
|
||||||
|
|
||||||
|
def jump65C02(self):
|
||||||
|
self.asm("jmp (%s_JMP,x)\n" % (self.niceName))
|
||||||
offset_suffix = ""
|
offset_suffix = ""
|
||||||
|
|
||||||
# Bit-shift jump table for 65C02
|
# Bit-shift jump table for 65C02
|
||||||
self.out("%s_JMP:" % (self.niceName) )
|
self.label("%s_JMP" % (self.niceName))
|
||||||
for shift in range(self.numShifts):
|
for shift in range(self.numShifts):
|
||||||
self.out("\t.addr %s_SHIFT%d" % (self.niceName, shift))
|
self.addr("%s_SHIFT%d" % (self.niceName, shift))
|
||||||
|
|
||||||
self.out(".else")
|
def jump6502(self):
|
||||||
# Fast jump table routine; faster and smaller than self-modifying code
|
# Fast jump table routine; faster and smaller than self-modifying code
|
||||||
self.out("\tlda %s_JMP+1,x" % (self.niceName))
|
self.asm("lda %s_JMP+1,x" % (self.niceName))
|
||||||
self.out("\tpha")
|
self.asm("pha")
|
||||||
self.out("\tlda %s_JMP,x" % (self.niceName))
|
self.asm("lda %s_JMP,x" % (self.niceName))
|
||||||
self.out("\tpha")
|
self.asm("pha")
|
||||||
self.out("\trts\n")
|
self.asm("rts\n")
|
||||||
|
|
||||||
# Bit-shift jump table for generic 6502
|
# Bit-shift jump table for generic 6502
|
||||||
self.out("%s_JMP:" % (self.niceName))
|
self.label("%s_JMP" % (self.niceName))
|
||||||
for shift in range(self.numShifts):
|
for shift in range(self.numShifts):
|
||||||
self.out("\t.addr %s_SHIFT%d-1" % (self.niceName,shift))
|
self.addr("%s_SHIFT%d-1" % (self.niceName,shift))
|
||||||
self.out(".endif")
|
|
||||||
|
|
||||||
def blitShift(self, shift):
|
def blitShift(self, shift):
|
||||||
# Blitting functions
|
# Blitting functions
|
||||||
|
@ -133,8 +203,8 @@ class Sprite(Listing):
|
||||||
# SAVE_AXY + RESTORE_AXY + rts + sprite jump table
|
# SAVE_AXY + RESTORE_AXY + rts + sprite jump table
|
||||||
cycleCount = 9 + 12 + 6 + 3 + 4 + 6
|
cycleCount = 9 + 12 + 6 + 3 + 4 + 6
|
||||||
|
|
||||||
self.out("%s_SHIFT%d:" % (self.niceName,shift))
|
self.label("%s_SHIFT%d" % (self.niceName,shift))
|
||||||
self.out("\tldx PARAM1")
|
self.asm("ldx PARAM1")
|
||||||
cycleCount += 3
|
cycleCount += 3
|
||||||
rowStartCode,extraCycles = self.rowStartCalculatorCode();
|
rowStartCode,extraCycles = self.rowStartCalculatorCode();
|
||||||
self.out(rowStartCode)
|
self.out(rowStartCode)
|
||||||
|
@ -347,18 +417,45 @@ def pixelColor(pixelData,row,col):
|
||||||
|
|
||||||
|
|
||||||
class HorizontalLookup(Listing):
|
class HorizontalLookup(Listing):
|
||||||
def __init__(self):
|
def __init__(self, assembler):
|
||||||
Listing.__init__(self)
|
Listing.__init__(self, assembler)
|
||||||
|
self.generate_hgr()
|
||||||
self.generate_tables()
|
self.generate_tables()
|
||||||
|
|
||||||
def generate_tables(self):
|
def generate_hgr(self):
|
||||||
self.out("DIV7_2:")
|
offsets = []
|
||||||
for pixel in range(140):
|
for y in range(192):
|
||||||
self.out("\t.byte $%02x" % ((pixel / 7)*2))
|
# From Apple Graphics and Arcade Game Design
|
||||||
|
a = y // 64
|
||||||
|
d = y - (64 * a)
|
||||||
|
b = d // 8
|
||||||
|
c = d - 8 * b
|
||||||
|
offsets.append((1024 * c) + (128 * b) + (40 * a))
|
||||||
|
|
||||||
self.out("\n\nMOD7_2:")
|
self.label("HGRROWS_H1")
|
||||||
|
for y in range(192):
|
||||||
|
addr = 0x2000 + offsets[y]
|
||||||
|
self.byte("$%02x" % (addr // 256))
|
||||||
|
|
||||||
|
self.label("HGRROWS_H2")
|
||||||
|
for y in range(192):
|
||||||
|
addr = 0x4000 + offsets[y]
|
||||||
|
self.byte("$%02x" % (addr // 256))
|
||||||
|
|
||||||
|
self.label("HGRROWS_L")
|
||||||
|
for y in range(192):
|
||||||
|
addr = offsets[y]
|
||||||
|
self.byte("$%02x" % (addr & 0xff))
|
||||||
|
|
||||||
|
def generate_tables(self):
|
||||||
|
self.label("DIV7_2")
|
||||||
for pixel in range(140):
|
for pixel in range(140):
|
||||||
self.out("\t.byte $%02x" % ((pixel % 7)*2))
|
self.byte("$%02x" % ((pixel / 7)*2))
|
||||||
|
|
||||||
|
self.out("\n")
|
||||||
|
self.label("MOD7_2")
|
||||||
|
for pixel in range(140):
|
||||||
|
self.byte("$%02x" % ((pixel % 7)*2))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -366,15 +463,26 @@ if __name__ == "__main__":
|
||||||
parser.add_argument("-v", "--verbose", default=0, action="count")
|
parser.add_argument("-v", "--verbose", default=0, action="count")
|
||||||
parser.add_argument("-t", "--tables", action="store_true", default=False, help="output only lookup tables for horizontal sprite shifts (division and modulus 7)")
|
parser.add_argument("-t", "--tables", action="store_true", default=False, help="output only lookup tables for horizontal sprite shifts (division and modulus 7)")
|
||||||
parser.add_argument("-x", "--xdraw", action="store_true", default=False, help="use XOR for sprite drawing")
|
parser.add_argument("-x", "--xdraw", action="store_true", default=False, help="use XOR for sprite drawing")
|
||||||
|
parser.add_argument("-s", "--syntax", default="cc65", nargs=1, choices=["cc65","mac65"], help="Assembler syntax (default: %(default)s)")
|
||||||
|
parser.add_argument("-p", "--processor", default="any", nargs=1, choices=["any","6502", "65C02"], help="Processor type (default: %(default)s)")
|
||||||
parser.add_argument("files", metavar="IMAGE", nargs="*", help="a PNG image [or a list of them]. PNG files must not have an alpha channel!")
|
parser.add_argument("files", metavar="IMAGE", nargs="*", help="a PNG image [or a list of them]. PNG files must not have an alpha channel!")
|
||||||
options, extra_args = parser.parse_known_args()
|
options, extra_args = parser.parse_known_args()
|
||||||
|
|
||||||
|
if options.syntax[0].lower() == "cc65":
|
||||||
|
syntax = CC65()
|
||||||
|
elif options.syntax[0].lower() == "mac65":
|
||||||
|
syntax = Mac65()
|
||||||
|
else:
|
||||||
|
print("Unknown assembler %s" % options.syntax)
|
||||||
|
parser.print_help()
|
||||||
|
|
||||||
if options.tables:
|
if options.tables:
|
||||||
print HorizontalLookup()
|
print HorizontalLookup(syntax)
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
for pngfile in options.files:
|
for pngfile in options.files:
|
||||||
try:
|
try:
|
||||||
print Sprite(pngfile, options.xdraw)
|
print Sprite(pngfile, syntax, options.xdraw, options.processor[0])
|
||||||
except RuntimeError:
|
except RuntimeError, e:
|
||||||
parser.usage()
|
print e
|
||||||
|
parser.print_help()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user