From b2842a1c397e55b1a7d404d49ec2b4c5bf439f67 Mon Sep 17 00:00:00 2001 From: Rob McMullen Date: Thu, 29 Jun 2017 11:48:25 -0700 Subject: [PATCH] Backing store driver and sample implementation for 3 byte * 11 row sprites --- HiSprite.py | 12 +++- Makefile.rob | 2 +- backingstore-3x11.s | 133 ++++++++++++++++++++++++++++++++++++++++++++ backingstore.s | 59 ++++++++++++++++++++ multitest.dsk | Bin 143360 -> 143360 bytes multitest.s | 35 +++++++----- 6 files changed, 224 insertions(+), 17 deletions(-) create mode 100644 backingstore-3x11.s create mode 100644 backingstore.s diff --git a/HiSprite.py b/HiSprite.py index e0204da..eb3c0d2 100755 --- a/HiSprite.py +++ b/HiSprite.py @@ -166,7 +166,7 @@ class Listing(object): class Sprite(Listing): - def __init__(self, pngfile, assembler, screen, xdraw=False, use_mask=False, processor="any", name=""): + def __init__(self, pngfile, assembler, screen, xdraw=False, use_mask=False, backing_store=False, processor="any", name=""): Listing.__init__(self, assembler) self.screen = screen @@ -175,6 +175,7 @@ class Sprite(Listing): self.xdraw = xdraw self.use_mask = use_mask + self.backing_store = backing_store self.processor = processor if not name: name = os.path.splitext(pngfile)[0] @@ -274,6 +275,10 @@ class Sprite(Listing): self.comment_line(str(c) + " " + str(m)) self.out("") + if self.backing_store: + byteWidth = len(colorStreams[0]) + self.asm("jsr savebg_%dx%d" % (byteWidth, self.height)) + self.asm("ldx PARAM1") cycleCount += 3 rowStartCode,extraCycles = self.rowStartCalculatorCode(); @@ -317,7 +322,7 @@ class Sprite(Listing): for chunkIndex in range(len(byteSplits)): # Optimization - if maskSplits[chunkIndex] == "01111111": + if maskSplits[chunkIndex] == "01111111" and not self.backing_store: optimizationCount += 1 else: value = self.binary_constant(byteSplits[chunkIndex]) @@ -638,6 +643,7 @@ if __name__ == "__main__": parser.add_argument("-r", "--rows", action="store_true", default=False, help="output row (y position) lookup tables") parser.add_argument("-x", "--xdraw", action="store_true", default=False, help="use XOR for sprite drawing") parser.add_argument("-m", "--mask", action="store_true", default=False, help="use mask for sprite drawing") + parser.add_argument("-b", "--backing-store", action="store_true", default=False, help="add code to store background") parser.add_argument("-a", "--assembler", default="cc65", choices=["cc65","mac65"], help="Assembler syntax (default: %(default)s)") 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)") @@ -667,7 +673,7 @@ if __name__ == "__main__": for pngfile in options.files: try: - listings.append(Sprite(pngfile, assembler, screen, options.xdraw, options.mask, options.processor, options.name)) + listings.append(Sprite(pngfile, assembler, screen, options.xdraw, options.mask, options.backing_store, options.processor, options.name)) except RuntimeError, e: print "%s: %s" % (pngfile, e) sys.exit(1) diff --git a/Makefile.rob b/Makefile.rob index ddb5922..0940bdc 100644 --- a/Makefile.rob +++ b/Makefile.rob @@ -15,7 +15,7 @@ collookupcolor.s: HiSprite.py python HiSprite.py -a mac65 -p 6502 -c > collookupcolor.s bwsprite.s: HiSprite.py collookupbw.s rowlookup.s $(BWSPRITE) - python HiSprite.py -a mac65 -p 6502 -s hgrbw $(BWSPRITE) -n bwsprite -m > bwsprite.s + python HiSprite.py -a mac65 -p 6502 -s hgrbw $(BWSPRITE) -n bwsprite -m -b > bwsprite.s colorsprite.s: HiSprite.py collookupcolor.s rowlookup.s $(COLORSPRITE) python HiSprite.py -a mac65 -p 6502 -s hgrcolor $(COLORSPRITE) -n colorsprite -m > colorsprite.s diff --git a/backingstore-3x11.s b/backingstore-3x11.s new file mode 100644 index 0000000..ef0a137 --- /dev/null +++ b/backingstore-3x11.s @@ -0,0 +1,133 @@ +; backing store test, hardcoded for 3x11 apple.png-sized sprite +; +; The backing store memory starts from some high address +; and grows downward in order to facilitate speedier restoring, because +; there will be different sized chunks to restore +; +; +; +; +; needs: +; bgstore: (lo byte, hi byte) 1 + the first byte of free memory. +; I.e. points just beyond the last byte +; PARAM0: (byte) x coord +; PARAM1: (byte) y coord +; +; everything else is known because the sizes of each erase/restore +; routine will be hardcoded. + +; modification of quinn's column sweep + +; memory needed for this chunk of background: +; 2: address of restore routine +; 1: x coordinate +; 1: y coordinate +; 33: number of bytes of background to save +SIZE_3X11 = 2 + 1 + 1 + 3*11 + +savebg_3x11 + sec + lda bgstore + sbc #SIZE_3X11 + sta bgstore + lda bgstore+1 + sbc #0 + sta bgstore+1 + ldy #0 + + lda #restorebg_3x11 + sta (bgstore),y + iny + lda PARAM0 + sta (bgstore),y + iny + lda PARAM1 + sta bgline + sta (bgstore),y + iny + +savebg_3x11_line + ldx bgline ; Calculate Y line + + lda HGRROWS_H1,x ; Compute hires row + sta savebg_3x11_col0+2 + sta savebg_3x11_col1+2 + sta savebg_3x11_col2+2 + lda HGRROWS_L,x + sta savebg_3x11_col0+1 + sta savebg_3x11_col1+1 + sta savebg_3x11_col2+1 + + ldx PARAM0 ; Compute hires column + lda DIV7_1,x + tax + +savebg_3x11_col0 + lda $2000,x + sta (bgstore),y + iny + inx +savebg_3x11_col1 + lda $2000,x + sta (bgstore),y + iny + inx +savebg_3x11_col2 + lda $2000,x + sta (bgstore),y + iny + + inc bgline + + cpy #SIZE_3X11 + bcc savebg_3x11_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_3x11 + ldx PARAM1 ; Calculate Y line + + lda HGRROWS_H1,x ; Compute hires row + sta restorebg_3x11_col0+2 + sta restorebg_3x11_col1+2 + sta restorebg_3x11_col2+2 + lda HGRROWS_L,x + sta restorebg_3x11_col0+1 + sta restorebg_3x11_col1+1 + sta restorebg_3x11_col2+1 + + ldx PARAM0 ; Compute hires column + lda DIV7_1,x + tax + + lda (bgstore),y +restorebg_3x11_col0 + sta $2000,x + iny + inx + lda (bgstore),y +restorebg_3x11_col1 + sta $2000,x + iny + inx + lda (bgstore),y +restorebg_3x11_col2 + sta $2000,x + iny + + inc PARAM1 + + cpy #SIZE_3X11 + bcc restorebg_3x11 + rts diff --git a/backingstore.s b/backingstore.s new file mode 100644 index 0000000..a23c127 --- /dev/null +++ b/backingstore.s @@ -0,0 +1,59 @@ +; Driver to restore the screen using all the saved data. +; +; The backing store is a stack that grows downward in order to restore the +; chunks in reverse order that they were saved. Each entry in the stack +; includes: +; +; 2 bytes: address of restore routine +; 1 byte: x coordinate +; 1 byte: y coordinate +; nn: x * y bytes of data, in lists of rows +; +; Note that sprites of different sizes will have different sized entries +; in the stack, so the entire list has to be processed in order. But you want +; that anyway, so it's not a big deal. +; +; The global variable 'bgstore' is used as the stack pointer. It musts be +; initialized to a page boundary, the stack grows downward from there. +; starting from the last byte on the previous page. E.g. if the initial +; value is $c000, the stack grows down using $bfff as the highest address, +; the initial bgstore value must point to 1 + the last usable byte +; +; All registers are clobbered because there's no real need to save them since +; this will be called from the main game loop. + +restorebg_init + lda #0 ; init backing store to end of free memory, $c000 + sta bgstore + lda #BGTOP + sta bgstore+1 + rts + + +restorebg_driver + ldy #0 + lda (bgstore),y + sta restorebg_jsr+1 + iny + lda (bgstore),y + sta restorebg_jsr+2 + iny + lda (bgstore),y + sta PARAM0 + iny + lda (bgstore),y + sta PARAM1 + iny +restorebg_jsr + jsr $ffff + + clc + lda bgstore + adc #SIZE_3X11 + sta bgstore + lda bgstore+1 + adc #0 + sta bgstore+1 + cmp #BGTOP + bcc restorebg_driver + rts diff --git a/multitest.dsk b/multitest.dsk index 132fbc1f1270cf48b6673e3f4999bc6ef7064bf9..6a57e27c69fce9e8d108171d2ee9f98b0b23b067 100644 GIT binary patch literal 143360 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, >BWSPRITE, 0, 0 + .byte >BWSPRITE, >BWSPRITE, >BWSPRITE, >BWSPRITE, >BWSPRITE, >BWSPRITE, >BWSPRITE, >BWSPRITE sprite_x - .byte 80, 64, 0, 0 + .byte 80, 64, 33, 83, 4, 9, 55, 18 sprite_y - .byte 116, 126, 0, 0 + .byte 116, 126, 40, 60, 80, 100, 120, 140 sprite_dx - .byte -1, 4, 0, 0 + .byte -1, -2, -3, -4, 1, 2, 3, 4 sprite_dy - .byte -3, 1, 0, 0 + .byte -4, -3, -2, -1, 4, 3, 2, 1 .include colorsprite.s @@ -203,3 +210,5 @@ sprite_dy .include rowlookup.s .include collookupbw.s .include collookupcolor.s + .include backingstore.s + .include backingstore-3x11.s