From 8951869372a88d2a429095b4346f2c96c89e42df Mon Sep 17 00:00:00 2001 From: Rob McMullen Date: Thu, 29 Jun 2017 23:14:39 -0700 Subject: [PATCH] Added multi-file generation in one step using a prefix * changed testcase to use second type of sprite * added hand-coded 3x8 backing store --- HiSprite.py | 69 +++++++++++++++++++----- Makefile.rob | 7 ++- backingstore-3x11.s | 124 ++++++++++++++++++++++++++++++++++++++++++-- backingstore.s | 4 +- multitest.dsk | Bin 143360 -> 143360 bytes multitest.s | 17 +++--- 6 files changed, 189 insertions(+), 32 deletions(-) diff --git a/HiSprite.py b/HiSprite.py index eb3c0d2..27c73a4 100755 --- a/HiSprite.py +++ b/HiSprite.py @@ -53,6 +53,8 @@ def slugify(s): class AssemblerSyntax(object): + extension = "s" + def asm(self, text): return "\t%s" % text @@ -74,6 +76,9 @@ class AssemblerSyntax(object): def origin(self, text): return self.asm("*= %s" % text) + def include(self, text): + return self.asm(".include \"%s\"" % text) + def binary_constant(self, value): try: # already a string @@ -97,6 +102,8 @@ class Mac65(AssemblerSyntax): class CC65(AssemblerSyntax): + extension = "s" + def label(self, text): return "%s:" % text @@ -108,11 +115,23 @@ class Listing(object): self.current = None self.desired_count = 1 self.stash_list = [] + self.slug = "sprite-driver" def __str__(self): self.flush_stash() return "\n".join(self.lines) + "\n" + def get_filename(self, basename): + return "%s-%s.%s" % (basename, self.slug.lower(), self.assembler.extension) + + def write(self, basename, disclaimer): + filename = self.get_filename(basename) + print("Writing to %s" % filename) + with open(filename, "w") as fh: + fh.write(disclaimer + "\n\n") + fh.write(str(self)) + return filename + def out(self, line): self.flush_stash() self.lines.append(line) @@ -135,6 +154,9 @@ class Listing(object): def addr(self, text): self.out(self.assembler.address(text)) + def include(self, text): + self.out(self.assembler.include(text)) + def flush_stash(self): if self.current is not None and len(self.stash_list) > 0: self.lines.append(self.current(", ".join(self.stash_list))) @@ -166,6 +188,8 @@ class Listing(object): class Sprite(Listing): + backing_store_sizes = set() + def __init__(self, pngfile, assembler, screen, xdraw=False, use_mask=False, backing_store=False, processor="any", name=""): Listing.__init__(self, assembler) self.screen = screen @@ -179,7 +203,7 @@ class Sprite(Listing): self.processor = processor if not name: name = os.path.splitext(pngfile)[0] - self.niceName = slugify(name) + self.slug = slugify(name) self.width = pngdata[0] self.height = pngdata[1] self.pixelData = list(pngdata[2]) @@ -189,7 +213,7 @@ class Sprite(Listing): def jumpTable(self): # Prologue - self.label("%s" % self.niceName) + self.label("%s" % self.slug) self.comment("%d bytes per row" % self.screen.byteWidth(self.width)) if self.processor == "any": @@ -234,13 +258,13 @@ class Sprite(Listing): self.asm("ldy PARAM0") self.asm("ldx MOD%d_%d,y" % (self.screen.numShifts, self.screen.bitsPerPixel)) - self.asm("jmp (%s_JMP,x)\n" % (self.niceName)) + self.asm("jmp (%s_JMP,x)\n" % (self.slug)) offset_suffix = "" # Bit-shift jump table for 65C02 - self.label("%s_JMP" % (self.niceName)) + self.label("%s_JMP" % (self.slug)) for shift in range(self.screen.numShifts): - self.addr("%s_SHIFT%d" % (self.niceName, shift)) + self.addr("%s_SHIFT%d" % (self.slug, shift)) def jump6502(self): self.save_axy_6502() @@ -248,16 +272,16 @@ class Sprite(Listing): self.asm("ldx MOD%d_%d,y" % (self.screen.numShifts, self.screen.bitsPerPixel)) # Fast jump table routine; faster and smaller than self-modifying code - self.asm("lda %s_JMP+1,x" % (self.niceName)) + self.asm("lda %s_JMP+1,x" % (self.slug)) self.asm("pha") - self.asm("lda %s_JMP,x" % (self.niceName)) + self.asm("lda %s_JMP,x" % (self.slug)) self.asm("pha") self.asm("rts\n") # Bit-shift jump table for generic 6502 - self.label("%s_JMP" % (self.niceName)) + self.label("%s_JMP" % (self.slug)) for shift in range(self.screen.numShifts): - self.addr("%s_SHIFT%d-1" % (self.niceName,shift)) + self.addr("%s_SHIFT%d-1" % (self.slug,shift)) def blitShift(self, shift): # Blitting functions @@ -267,7 +291,7 @@ class Sprite(Listing): # SAVE_AXY + RESTORE_AXY + rts + sprite jump table cycleCount = 9 + 12 + 6 + 3 + 4 + 6 - self.label("%s_SHIFT%d" % (self.niceName,shift)) + self.label("%s_SHIFT%d" % (self.slug,shift)) colorStreams = self.screen.byteStreamsFromPixels(shift, self) maskStreams = self.screen.byteStreamsFromPixels(shift, self, True) @@ -278,6 +302,7 @@ class Sprite(Listing): if self.backing_store: byteWidth = len(colorStreams[0]) self.asm("jsr savebg_%dx%d" % (byteWidth, self.height)) + self.backing_store_sizes.add((byteWidth, self.height)) self.asm("ldx PARAM1") cycleCount += 3 @@ -594,6 +619,7 @@ class HGRBW(HGR): class RowLookup(Listing): def __init__(self, assembler, screen): Listing.__init__(self, assembler) + self.slug = "hgrrows" self.generate_y(screen) def generate_y(self, screen): @@ -615,6 +641,7 @@ class RowLookup(Listing): class ColLookup(Listing): def __init__(self, assembler, screen): Listing.__init__(self, assembler) + self.slug = "hgrcols-%dx%d" % (screen.numShifts, screen.bitsPerPixel) self.generate_x(screen) def generate_x(self, screen): @@ -648,6 +675,7 @@ if __name__ == "__main__": parser.add_argument("-p", "--processor", default="any", choices=["any","6502", "65C02"], help="Processor type (default: %(default)s)") parser.add_argument("-s", "--screen", default="hgrcolor", choices=["hgrcolor","hgrbw"], help="Screen format (default: %(default)s)") parser.add_argument("-n", "--name", default="", help="Name for generated assembly function (default: based on image filename)") + parser.add_argument("-o", "--output-prefix", default="", help="Base name to create a set of output files. If not supplied, all code will be sent to stdout.") 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() @@ -670,6 +698,7 @@ if __name__ == "__main__": sys.exit(1) listings = [] + luts = {} for pngfile in options.files: try: @@ -680,6 +709,13 @@ if __name__ == "__main__": except png.Error, e: print "%s: %s" % (pngfile, e) sys.exit(1) + if options.output_prefix: + r = RowLookup(assembler, screen) + luts[r.slug] = r + c = ColLookup(assembler, screen) + luts[c.slug] = c + + listings.extend([luts[k] for k in sorted(luts.keys())]) if options.rows: listings.append(RowLookup(assembler, screen)) @@ -688,7 +724,14 @@ if __name__ == "__main__": listings.append(ColLookup(assembler, screen)) if listings: - print disclaimer + if options.output_prefix: + driver = Listing(assembler) + for source in listings: + genfile = source.write(options.output_prefix, disclaimer) + driver.include(genfile) + driver.write(options.output_prefix, disclaimer) + else: + print disclaimer - for section in listings: - print section + for section in listings: + print section diff --git a/Makefile.rob b/Makefile.rob index 0940bdc..a1d3d72 100644 --- a/Makefile.rob +++ b/Makefile.rob @@ -28,7 +28,10 @@ colortest.dsk: HiSprite.py colortest.s bwsprite.s atasm -ocolortest.xex colortest.s -Lcolortest.var -gcolortest.lst atrcopy colortest.dsk boot -b colortest.xex --brun 6000 -f -multitest.dsk: HiSprite.py multitest.s colorsprite.s bwsprite.s +multitest-sprite-driver.s: HiSprite.py $(BWSPRITE) + python HiSprite.py -a mac65 -p 6502 -s hgrbw -m -b -o multitest $(BWSPRITE) $(COLORSPRITE) + +multitest.dsk: HiSprite.py multitest.s multitest-sprite-driver.s atasm -omultitest.xex multitest.s -Lmultitest.var -gmultitest.lst atrcopy multitest.dsk boot -b multitest.xex --brun 6000 -f @@ -36,4 +39,4 @@ clean: rm -f rowlookup.s collookupbw.s collookupcolor.s rm -f bwtest.dsk bwtest.xex bwtest.var bwtest.lst rm -f colortest.dsk colortest.xex colortest.var colortest.lst - rm -f multitest.dsk multitest.xex multitest.var multitest.lst + rm -f multitest.dsk multitest.xex multitest.var multitest.lst multitest-sprite-driver.s multitest-bwsprite.s multitest-hgrcols-7x1.s multitest-hgrrows.s diff --git a/backingstore-3x11.s b/backingstore-3x11.s index ef0a137..7dbacbc 100644 --- a/backingstore-3x11.s +++ b/backingstore-3x11.s @@ -26,6 +26,7 @@ SIZE_3X11 = 2 + 1 + 1 + 3*11 savebg_3x11 + ; reserve space in the backing store stack sec lda bgstore sbc #SIZE_3X11 @@ -33,8 +34,9 @@ savebg_3x11 lda bgstore+1 sbc #0 sta bgstore+1 - ldy #0 + ; save the metadata + ldy #0 lda #restorebg_3X8 + sta (bgstore),y + iny + lda PARAM0 + sta (bgstore),y + iny + lda PARAM1 + sta SCRATCH0 + sta (bgstore),y + iny + +savebg_3X8_line + ; save a line, starting from the topmost and working down + ldx SCRATCH0 ; Calculate Y line + + lda HGRROWS_H1,x ; Compute hires row + sta savebg_3X8_col0+2 + sta savebg_3X8_col1+2 + sta savebg_3X8_col2+2 + lda HGRROWS_L,x + sta savebg_3X8_col0+1 + sta savebg_3X8_col1+1 + sta savebg_3X8_col2+1 + + ldx PARAM0 ; Compute hires column + lda DIV7_1,x + tax + +savebg_3X8_col0 + lda $2000,x + sta (bgstore),y + iny + inx +savebg_3X8_col1 + lda $2000,x + sta (bgstore),y + iny + inx +savebg_3X8_col2 + lda $2000,x + sta (bgstore),y + iny + + inc SCRATCH0 + + cpy #SIZE_3X8 + bcc savebg_3X8_line + + rts + +; bgstore will be pointing right to the data to be blitted back to the screen, +; which is 4 bytes into the bgstore array. Everything before the data will have +; already been pulled off by the driver in order to figure out which restore +; routine to call. Y will be 4 upon entry, and PARAM0 and PARAM1 will be +; filled with the x & y values. +; +; also, no need to save registers because this is being called from a driver +; that will do all of that. +restorebg_3X8 + ldx PARAM1 ; Calculate Y line + + lda HGRROWS_H1,x ; Compute hires row + sta restorebg_3X8_col0+2 + sta restorebg_3X8_col1+2 + sta restorebg_3X8_col2+2 + lda HGRROWS_L,x + sta restorebg_3X8_col0+1 + sta restorebg_3X8_col1+1 + sta restorebg_3X8_col2+1 + + ldx PARAM0 ; Compute hires column + lda DIV7_1,x + tax + + lda (bgstore),y +restorebg_3X8_col0 + sta $2000,x + iny + inx + lda (bgstore),y +restorebg_3X8_col1 + sta $2000,x + iny + inx + lda (bgstore),y +restorebg_3X8_col2 + sta $2000,x + iny + + inc PARAM1 + + cpy #SIZE_3X8 + bcc restorebg_3X8 + rts diff --git a/backingstore.s b/backingstore.s index a23c127..a558136 100644 --- a/backingstore.s +++ b/backingstore.s @@ -48,8 +48,8 @@ restorebg_jsr jsr $ffff clc - lda bgstore - adc #SIZE_3X11 + tya ; y contains the number of bytes processed + adc bgstore sta bgstore lda bgstore+1 adc #0 diff --git a/multitest.dsk b/multitest.dsk index 8d654b45aef064c9ed53ed32dc9f501bf2e38254..211df6040d54204ac43dd6d798eddb571258b8ca 100644 GIT binary patch literal 143360 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 diff --git a/multitest.s b/multitest.s index 72e01b2..6304668 100644 --- a/multitest.s +++ b/multitest.s @@ -21,10 +21,9 @@ SCRATCH0 = $19 SCRATCH1 = $1a SPRITEPTR_L = $1b SPRITEPTR_H = $1c +BGSTORE = $fa BGTOP = $c0 ; page number of first byte beyond top of backing store stack -bgstore = $80 -bgline = $82 ; constants MAXPOSX = 250 @@ -204,10 +203,10 @@ sprite_active .byte 1, 1, 1, 1, 1, 1, 1, 1, $ff ; 1 = active, 0 = skip, $ff = end of list sprite_l - .byte BWSPRITE, >BWSPRITE, >BWSPRITE, >BWSPRITE, >BWSPRITE, >BWSPRITE, >BWSPRITE, >BWSPRITE + .byte >APPLE_SPRITE9X11, >APPLE_SPRITE9X11, >APPLE_SPRITE9X11, >APPLE_SPRITE9X11, >APPLE_SPRITE9X11, >APPLE_SPRITE9X11, >MOLDY_BURGER, >MOLDY_BURGER sprite_x .byte 80, 164, 33, 245, 4, 9, 255, 18 @@ -229,10 +228,6 @@ sprite_diry - .include colorsprite.s - .include bwsprite.s - .include rowlookup.s - .include collookupbw.s - .include collookupcolor.s - .include backingstore.s - .include backingstore-3x11.s +.include multitest-sprite-driver.s +.include backingstore.s +.include backingstore-3x11.s