mirror of
https://github.com/robmcmullen/asmgen.git
synced 2024-06-01 05:41:29 +00:00
Added generated code for backing store save/restore
This commit is contained in:
parent
695f589d1b
commit
d7ed49b7c2
160
HiSprite.py
160
HiSprite.py
|
@ -122,6 +122,9 @@ class Listing(object):
|
||||||
self.flush_stash()
|
self.flush_stash()
|
||||||
return "\n".join(self.lines) + "\n"
|
return "\n".join(self.lines) + "\n"
|
||||||
|
|
||||||
|
def add_listing(self, other):
|
||||||
|
self.lines.extend(other.lines)
|
||||||
|
|
||||||
def get_filename(self, basename):
|
def get_filename(self, basename):
|
||||||
return "%s-%s.%s" % (basename, self.slug.lower(), self.assembler.extension)
|
return "%s-%s.%s" % (basename, self.slug.lower(), self.assembler.extension)
|
||||||
|
|
||||||
|
@ -686,6 +689,157 @@ class ColLookup(Listing):
|
||||||
self.byte("$%02x" % ((pixel % screen.numShifts) * 2), screen.numShifts)
|
self.byte("$%02x" % ((pixel % screen.numShifts) * 2), screen.numShifts)
|
||||||
|
|
||||||
|
|
||||||
|
class BackingStore(Listing):
|
||||||
|
# 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
|
||||||
|
|
||||||
|
def __init__(self, assembler, byte_width, row_height):
|
||||||
|
Listing.__init__(self, assembler)
|
||||||
|
self.byte_width = byte_width
|
||||||
|
self.row_height = row_height
|
||||||
|
self.save_label = "savebg_%dx%d" % (byte_width, row_height)
|
||||||
|
self.restore_label = "restorebg_%dx%d" % (byte_width, row_height)
|
||||||
|
self.space_needed = self.compute_size()
|
||||||
|
self.create_save()
|
||||||
|
self.out()
|
||||||
|
self.create_restore()
|
||||||
|
self.out()
|
||||||
|
|
||||||
|
def compute_size(self):
|
||||||
|
return 2 + 1 + 1 + (self.byte_width * self.row_height)
|
||||||
|
|
||||||
|
def create_save(self):
|
||||||
|
self.label(self.save_label)
|
||||||
|
|
||||||
|
# reserve space in the backing store stack
|
||||||
|
self.asm("sec")
|
||||||
|
self.asm("lda bgstore")
|
||||||
|
self.asm("sbc #%d" % self.space_needed)
|
||||||
|
self.asm("sta bgstore")
|
||||||
|
self.asm("lda bgstore+1")
|
||||||
|
self.asm("sbc #0")
|
||||||
|
self.asm("sta bgstore+1")
|
||||||
|
|
||||||
|
# save the metadata
|
||||||
|
self.asm("ldy #0")
|
||||||
|
self.asm("lda #<%s" % self.restore_label)
|
||||||
|
self.asm("sta (bgstore),y")
|
||||||
|
self.asm("iny")
|
||||||
|
self.asm("lda #>%s" % self.restore_label)
|
||||||
|
self.asm("sta (bgstore),y")
|
||||||
|
self.asm("iny")
|
||||||
|
self.asm("lda PARAM0")
|
||||||
|
self.asm("sta (bgstore),y")
|
||||||
|
self.asm("iny")
|
||||||
|
self.asm("lda PARAM1")
|
||||||
|
|
||||||
|
# Note that we can't clobber PARAM1 like the restore routine can
|
||||||
|
# because this is called in the sprite drawing routine and these
|
||||||
|
# values must be retained to draw the sprite in the right place!
|
||||||
|
self.asm("sta SCRATCH0")
|
||||||
|
self.asm("sta (bgstore),y")
|
||||||
|
self.asm("iny")
|
||||||
|
|
||||||
|
loop_label, col_label = self.smc_row_col(self.save_label, "SCRATCH0")
|
||||||
|
|
||||||
|
for c in range(self.byte_width):
|
||||||
|
self.label(col_label % c)
|
||||||
|
self.asm("lda $2000,x")
|
||||||
|
self.asm("sta (bgstore),y")
|
||||||
|
self.asm("iny")
|
||||||
|
if c < self.byte_width - 1:
|
||||||
|
# last loop doesn't need this
|
||||||
|
self.asm("inx")
|
||||||
|
|
||||||
|
self.asm("inc SCRATCH0")
|
||||||
|
|
||||||
|
self.asm("cpy #%d" % self.space_needed)
|
||||||
|
self.asm("bcc %s" % loop_label)
|
||||||
|
|
||||||
|
self.asm("rts")
|
||||||
|
|
||||||
|
def smc_row_col(self, label, row_var):
|
||||||
|
# set up smc for hires column, because the starting column doesn't
|
||||||
|
# change when moving to the next row
|
||||||
|
self.asm("ldx PARAM0")
|
||||||
|
self.asm("lda DIV7_1,x")
|
||||||
|
smc_label = "%s_smc1" % label
|
||||||
|
self.asm("sta %s+1" % smc_label)
|
||||||
|
|
||||||
|
loop_label = "%s_line" % label
|
||||||
|
# save a line, starting from the topmost and working down
|
||||||
|
self.label(loop_label)
|
||||||
|
self.asm("ldx %s" % row_var)
|
||||||
|
|
||||||
|
self.asm("lda HGRROWS_H1,x")
|
||||||
|
col_label = "%s_col%%s" % label
|
||||||
|
for c in range(self.byte_width):
|
||||||
|
self.asm("sta %s+2" % (col_label % c))
|
||||||
|
self.asm("lda HGRROWS_L,x")
|
||||||
|
for c in range(self.byte_width):
|
||||||
|
self.asm("sta %s+1" % (col_label % c))
|
||||||
|
|
||||||
|
self.label(smc_label)
|
||||||
|
self.asm("ldx #$ff")
|
||||||
|
return loop_label, col_label
|
||||||
|
|
||||||
|
def create_restore(self):
|
||||||
|
# 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.
|
||||||
|
self.label(self.restore_label)
|
||||||
|
|
||||||
|
# we can clobber the heck out of PARAM1 because we're being called from
|
||||||
|
# the restore driver and when we return we are just going to load it up
|
||||||
|
# with the next value anyway.
|
||||||
|
loop_label, col_label = self.smc_row_col(self.restore_label, "PARAM1")
|
||||||
|
|
||||||
|
for c in range(self.byte_width):
|
||||||
|
self.asm("lda (bgstore),y")
|
||||||
|
self.label(col_label % c)
|
||||||
|
self.asm("sta $2000,x")
|
||||||
|
self.asm("iny")
|
||||||
|
if c < self.byte_width - 1:
|
||||||
|
# last loop doesn't need this
|
||||||
|
self.asm("inx")
|
||||||
|
|
||||||
|
self.asm("inc PARAM1")
|
||||||
|
self.asm("cpy #%d" % self.space_needed)
|
||||||
|
self.asm("bcc %s" % loop_label)
|
||||||
|
|
||||||
|
self.asm("rts")
|
||||||
|
|
||||||
|
|
||||||
|
class BackingStoreDriver(Listing):
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# variables used:
|
||||||
|
# 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 are hardcoded because this is a sprite *compiler*.
|
||||||
|
def __init__(self, assembler, sizes):
|
||||||
|
Listing.__init__(self, assembler)
|
||||||
|
self.slug = "backing-store"
|
||||||
|
for byte_width, row_height in sizes:
|
||||||
|
code = BackingStore(assembler, byte_width, row_height)
|
||||||
|
self.add_listing(code)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
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.
|
||||||
|
@ -731,13 +885,14 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
for pngfile in options.files:
|
for pngfile in options.files:
|
||||||
try:
|
try:
|
||||||
listings.append(Sprite(pngfile, assembler, screen, options.xdraw, options.mask, options.backing_store, options.clobber, options.processor, options.name))
|
sprite_code = Sprite(pngfile, assembler, screen, options.xdraw, options.mask, options.backing_store, options.clobber, options.processor, options.name)
|
||||||
except RuntimeError, e:
|
except RuntimeError, e:
|
||||||
print "%s: %s" % (pngfile, e)
|
print "%s: %s" % (pngfile, e)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except png.Error, e:
|
except png.Error, e:
|
||||||
print "%s: %s" % (pngfile, e)
|
print "%s: %s" % (pngfile, e)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
listings.append(sprite_code)
|
||||||
if options.output_prefix:
|
if options.output_prefix:
|
||||||
r = RowLookup(assembler, screen)
|
r = RowLookup(assembler, screen)
|
||||||
luts[r.slug] = r
|
luts[r.slug] = r
|
||||||
|
@ -754,6 +909,9 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
if listings:
|
if listings:
|
||||||
if options.output_prefix:
|
if options.output_prefix:
|
||||||
|
if Sprite.backing_store_sizes:
|
||||||
|
backing_store_code = BackingStoreDriver(assembler, Sprite.backing_store_sizes)
|
||||||
|
listings.append(backing_store_code)
|
||||||
driver = Listing(assembler)
|
driver = Listing(assembler)
|
||||||
for source in listings:
|
for source in listings:
|
||||||
genfile = source.write(options.output_prefix, disclaimer)
|
genfile = source.write(options.output_prefix, disclaimer)
|
||||||
|
|
|
@ -1,254 +0,0 @@
|
||||||
; 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
|
|
||||||
; reserve space in the backing store stack
|
|
||||||
sec
|
|
||||||
lda bgstore
|
|
||||||
sbc #SIZE_3X11
|
|
||||||
sta bgstore
|
|
||||||
lda bgstore+1
|
|
||||||
sbc #0
|
|
||||||
sta bgstore+1
|
|
||||||
|
|
||||||
; save the metadata
|
|
||||||
ldy #0
|
|
||||||
lda #<restorebg_3x11
|
|
||||||
sta (bgstore),y
|
|
||||||
iny
|
|
||||||
lda #>restorebg_3x11
|
|
||||||
sta (bgstore),y
|
|
||||||
iny
|
|
||||||
lda PARAM0
|
|
||||||
sta (bgstore),y
|
|
||||||
iny
|
|
||||||
lda PARAM1
|
|
||||||
sta SCRATCH0
|
|
||||||
sta (bgstore),y
|
|
||||||
iny
|
|
||||||
|
|
||||||
; set up smc for hires column, because the starting column doesn't change
|
|
||||||
; when moving to the next row
|
|
||||||
ldx PARAM0
|
|
||||||
lda DIV7_1,x
|
|
||||||
sta savebg_3x11_smc1+1
|
|
||||||
|
|
||||||
savebg_3x11_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_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
|
|
||||||
|
|
||||||
savebg_3x11_smc1
|
|
||||||
ldx #$ff
|
|
||||||
|
|
||||||
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 SCRATCH0
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
SIZE_3X8 = 2 + 1 + 1 + 3*8
|
|
||||||
|
|
||||||
savebg_3X8
|
|
||||||
; reserve space in the backing store stack
|
|
||||||
sec
|
|
||||||
lda bgstore
|
|
||||||
sbc #SIZE_3X8
|
|
||||||
sta bgstore
|
|
||||||
lda bgstore+1
|
|
||||||
sbc #0
|
|
||||||
sta bgstore+1
|
|
||||||
|
|
||||||
; save the metadata
|
|
||||||
ldy #0
|
|
||||||
lda #<restorebg_3X8
|
|
||||||
sta (bgstore),y
|
|
||||||
iny
|
|
||||||
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
|
|
BIN
multitest.dsk
BIN
multitest.dsk
Binary file not shown.
|
@ -251,4 +251,3 @@ sprite_diry
|
||||||
|
|
||||||
.include multitest-sprite-driver.s
|
.include multitest-sprite-driver.s
|
||||||
.include backingstore.s
|
.include backingstore.s
|
||||||
.include backingstore-3x11.s
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user