
;  You'll have fun with this!!!

#name FastSpr
#type &ffa
#base 0
#set Swibase = &47d00

struct v {
  .screenstart	DCD 0
  .screensize	DCD 0
  .vpix		DCD 0
  .hbytes	DCD 0
  .modesize	DCD 0
  .screenuse	DCD 0
  .datastart	DCD 0
  .cminx	DCD 0
  .cminy	DCD 0
  .cmaxx	DCD 0
  .cmaxy	DCD 0
  .backdropstr	DCD 0
  .flashstr	DCD 0
  .startblock	DBD &40
  .sizeof
}
  
DCD 0
DCD init
DCD final
DCD service
DCD title
DCD helpstring
DCD helptable
DCD Swibase
DCD swicode
DCD switab
DCD 0

.title
DCB "FastSpr",0
ALIGN
.helpstring
DCB "FastSpr",9,9,"3.01 (16 Oct 1994)",0
ALIGN
.helptable
DCB "FastSpr"
DCB 0
ALIGN
DCD 0
DCD 0
DCD 0
DCD help
DCB "FastSprPlot"
DCB 0
ALIGN
DCD plot
DCD &0003FF03
DCD plotsyn
DCD plothelp
DCB "FastSprLoad"
DCB 0
ALIGN
DCD fsploadcommand
DCD &0002FF01
DCD fsploadsyn
DCD fsploadhelp
DCB "FastSprWipe"
DCB 0
ALIGN
DCD wipecommand
DCD &0001FF00
DCD fspwipesyn
DCD fspwipehelp
DCB "FastSprBackdrop"
DCB 0
ALIGN
DCD backdrop
DCD &0001FF01
DCD backdropsyn
DCD backdrophelp
DCB "FastSprFlash"
DCB 0
ALIGN
DCD flash
DCD &0001FF01
DCD flashsyn
DCD flashhelp
DCB "FastSprSWIs"
DCB 0
ALIGN
DCD 0
DCD 0
DCD 0
DCD swihelp
DCD 0    ;*** END MARKER ***

.plothelp
DCB 27,0," issues a plot command via FastSpr_Plot.  Use this command for testing only please (very slow).",10,13
.plotsyn
DCB 27,1," <number> <x coord> <y coord>",0

.help
DCB 27,0," is an optimised sprite plotter, using a special sprite format.",10,13
DCB " A.Southgate 1994 - may be freely included in commercial or non-commercial software.",10,13
DCB "The flash facility is not active in this release.",10,13
DCB 0

.fsploadhelp
DCB 27,0," loads a FastSpr file into the RMA.",10,13
.fsploadsyn
DCB 27,1," [pool] <filename>",0
.fspwipehelp
DCB 27,0," removes one or more FastSpr files from memory.",10,13
.fspwipesyn
DCB 27,1," [pool]",0
.backdrophelp
DCB 27,0," sets the colour used to fill the clip window, used by the SWI ",34,"FastSpr_ClearWindow",34,".  Colours are numbered 0-255 as in !Paint.",10,13
.backdropsyn
DCB 27,1," <colour>",0
.flashhelp
DCB 27,0," sets the colour used to paint a sprite when flash is specified by setting bit 30 in the sprite number.  Colours are numbered 0-255 as in !Paint.",10,13
DCB "*** SetFlash is inactive in this release ***",10,13
.flashsyn
DCB 27,1," <colour>",0
.swihelp
DCB "The module supports the following SWIs, based at &47D00.",10,13,10,13
DCB 9,"&47D00",9,34,"FastSpr_Plot",34,",spritenum,x,y",10,13
DCB 9,"&47D01",9,34,"FastSpr_ClearWindow",34,10,13
DCB 9,"&47D02",9,34,"FastSpr_SetClipWindow",34,",xmix,ymin,xmax,ymax",10,13
DCB 9,"&47D03",9,34,"FastSpr_Load",34,",filename$,pool",10,13
DCB 9,"&47D04",9,34,"FastSpr_GetAddress",34," TO PlotsAdr,ClearsAdr,BanksAdr,,VarsAdr",10,13
DCB 9,"&47D05",9,34,"FastSpr_SetBackdrop",34,",colour",10,13
DCB 9,"&47D06",9,34,"FastSpr_ScreenBank",34,",bank",10,13
DCB 9,"&47D07",9,34,"FastSpr_SpritesAreAt",34,",address",10,13
DCB 9,"&47D08",9,34,"FastSpr_ReadSize",34,",number TO xsize,ysize",10,13
DCB 9,"&47D09",9,34,"FastSpr_GetPointer",34,",pool TO address",10,13
DCB 9,"&47D0A",9,34,"FastSpr_SetFlash",34,",colour",10,13
DCB 10,13
DCB "PlotsAdr, ClearsAdr and BanksAdr are call addresses for the three routines, to bypass the SWI system.",10,13
DCB "VarsAdr is the address of FastSprs variables.",10,13
DCB "*** SetFlash is inactive in this release ***",10,13
DCB 0


ALIGN

.switab
DCB "FastSpr"
DCB 0
DCB "Plot",0
DCB "ClearWindow",0
DCB "SetClipWindow",0
DCB "Load",0
DCB "GetAddress",0
DCB "SetBackdrop",0
DCB "ScreenBank",0
DCB "SpritesAreAt",0
DCB "ReadSize",0
DCB "GetPointer",0
DCB "SetFlash",0
DCB 0; *** END MARKER ***
ALIGN

#set swino = 11

.service
CMP R1,#&46
MOVNES PC,R14
STMFD R13!,{R0-R2,R14}
LDR R12,[R12]
BL moderead
LDMFD R13!,{R0-R2,PC}

.swicode
LDR R12,[R12]
CMP R11,#0
BEQ plotswi
CMP R11,#swino
BGE unknownswi
ADR R10,swiofstab
LDR R11,[R10,R11,LSL #2]
ADD PC,R10,R11
.swiofs
.swiofstab
DCD plotswi 		- swiofs
DCD clearwindowswi   	- swiofs
DCD setclipwindowswi	- swiofs
DCD fsploadswi		- swiofs
DCD getaddressswi	- swiofs
DCD setbackdropswi	- swiofs
DCD setscreenbankswi	- swiofs
DCD spritesareatswi	- swiofs
DCD readsizeswi		- swiofs
DCD getpoolpointerswi	- swiofs
DCD setflashswi		- swiofs


.setclipwindowswi
STMFD R13!,{R4,R14}
CMP R0,#0
CMPGE R1,#0
BLT badwindow
LDR R4,[R12,#v.hbytes]
CMP R2,R4
BGT badwindow
LDR R4,[R12,#v.vpix]
CMP R3,R4
BGT badwindow
CMP R0,R2
CMPLT R1,R3
BGE badwindow
CMP R0,#2
CMPLT R1,#1
CMPLT R2,#3
BLT badwindow
STR R0,[R12,#v.cminx]
STR R1,[R12,#v.cminy]
STR R2,[R12,#v.cmaxx]
STR R3,[R12,#v.cmaxy]
LDMFD R13!,{R4,PC}


.spritesareatswi
STMFD R13!,{R1-R2,R14}
LDR R2,[R12,#v.datastart]
STR R0,[R12,#v.datastart]
MOV R0,#7
CMP R2,#&1800000
SWIGE XOS_Module
LDMFD R13!,{R1-R2,PC}^

.getpoolpointerswi
STMFD R13!,{R14}
AND R0,R0,#&3F
CMP R0,#0
ADDEQ R0,R12,#v.datastart
LDMEQFD R13!,{PC}^
MOV R0,R0,LSL #2
ADD R0,R12,R0
ADD R0,R0,#v.startblock
LDMFD R13!,{PC}^

.wipecommand
STMFD R13!,{R14}
LDR R12,[R12]
CMP R1,#0
BEQ wipeall
MOV R1,R0
MOV R0,#10
SWI OS_ReadUnsigned
MOV R0,#0
MOV R1,R2
BL fsploadswi
LDMFD R13!,{PC}
.wipeall
BL releasestartblock
LDMFD R13!,{PC}

.fsploadcommand

LDR R12,[R12]
CMP R1,#1
MOVEQ R1,#0;pool 0
BEQ fsploadswi
STMFD R13!,{R14}
MOV R1,R0
MOV R0,#10
SWI OS_ReadUnsigned
MOV R0,R1
MOV R1,R2
BL fsploadswi
LDMFD R13!,{PC}



.fsploadswi
STMFD R13!,{R1-R9,R14}
MOV R6,R0
MOV R0,R1
BL getpoolpointerswi
MOV R10,R0
LDR R2,[R10]
MOV R0,#0
STR R0,[R10]
MOV R0,#7
TST R2,#1
BIC R2,R2,#3
SWINE XOS_Module
MOV R0,#0
STR R0,[R10]
MOV R1,R6
CMP R1,#0
LDMEQFD R13!,{R1-R9,PC}^
MOV R0,#5
SWI OS_File
CMP R0,#1
LDMNEFD R13!,{R1-R9,R14}
BNE badfileerr
MOV R6,R1
MOV R0,#6
MOV R3,R4
SWI XOS_Module
LDMVSFD R13!,{R1-R9,R14}
BVS nospaceerr
ORR R2,R2,#1
STR R2,[R10]
BIC R2,R2,#3
MOV R3,#0
MOV R1,R6
MOV R0,#&FF
SWI OS_File
LDR R0,[R10]
BIC R0,R0,#3
LDR R0,[R0]
LDR R1,idbyte1
CMP R0,R1
LDR R1,idbyte2
CMPNE R0,R1
LDMNEFD R13!,{R1-R9,R14}
BNE badfileerr2
LDMFD R13!,{R1-R9,PC}^

.backdrop
STMFD R13!,{R14}
MOV R1,R0
MOV R0,#10
ORR R0,R0,#3<<30
SWI OS_ReadUnsigned
MOV R0,R2
BL setbackdropswi
LDMFD R13!,{PC}

.flash
STMFD R13!,{R14}
MOV R1,R0
MOV R0,#10
ORR R0,R0,#3<<30
SWI OS_ReadUnsigned
MOV R0,R2
BL setflashswi
LDMFD R13!,{PC}

.plot
STMFD R13!,{R14}
LDR R12,[R12]
MOV R1,R0
MOV R0,#10
SWI OS_ReadUnsigned
MOV R3,R2
SWI OS_ReadUnsigned
MOV R4,R2
SWI OS_ReadUnsigned
MOV R0,R3
MOV R1,R4
BL plotswi
LDMFD R13!,{PC}

.init
STMFD R13!,{R1-R11,R14}
MOV R4,R12
LDR R12,[R12]
CMP R12,#0
BNE dontclaim
MOV R0,#6
MOV R3,#v.sizeof         ;variable block size
SWI OS_Module
STR R2,[R4]
MOV R12,R2
.dontclaim
STR R12,varstr
MOV R1,#v.sizeof
MOV R0,#0
MOV R2,R12
.loop11
STR R0,[R2],#4
SUBS R1,R1,#4
BGT loop11
BL moderead
MVN R0,#0
STR R0,[R12,#v.flashstr]
LDMFD R13!,{R1-R11,PC}

.releasestartblock
STMFD R13!,{R14}
LDR R2,[R12,#v.datastart]
MOV R0,#0
STR R0,[R12,#v.datastart]
MOV R0,#7
TST R2,#1
BIC R2,R2,#3
SWINE XOS_Module       ;don't generate errors while finalising

ADD R4,R12,#v.startblock
MOV R5,#&3F

.loopx
LDR R2,[R4]
MOV R0,#0
STR R0,[R4],#4
MOV R0,#7
TST R2,#1
BIC R2,R2,#3
SWINE XOS_Module
SUBS R5,R5,#1
BGT loopx
LDMFD R13!,{PC}^


.final
STMFD R13!,{R1-R11,R14}; needs a rewrite
LDR R12,[R12]
BL releasestartblock
CMP R10,#0
MOV R0,#7
MOV R2,R12
SWINE XOS_Module
LDMFD R13!,{R1-R11,PC}^


.moderead
STMFD R13!,{R14}
MOV R0,#112
MOV R1,#1
SWI OS_Byte
MOV R3,R1
ADR R0,vdutab
ADD R1,R12,#v.screenstart
SWI OS_ReadVduVariables
MOV R0,#112
MOV R1,R3
SWI OS_Byte
LDR R0,[R12,#v.hbytes]
LDR R1,[R12,#v.modesize]
MVN R2,#0
.vduloop
SUBS R1,R1,R0
ADD R2,R2,#1
BPL vduloop
STR R2,[R12,#v.vpix]
MOV R0,#0
STR R0,[R12,#v.cminx]
STR R0,[R12,#v.cminy]
LDR R0,[R12,#v.hbytes]
STR R0,[R12,#v.cmaxx]
LDR R0,[R12,#v.vpix]
STR R0,[R12,#v.cmaxy]
MOV R0,#0
BL setscreenbankswi
LDMFD R13!,{PC}
.vdutab
DCD 148;  screenstart
DCD 150;  screensize
DCD 5  ;  vert.pix.res
DCD 6  ;  bytes per row
DCD 7  ;  modesize
DCD -1

.getaddressswi
STMFD R13!,{R14}
ADR R0,plotveneer
ADR R1,clearveneer
ADR R2,bankveneer
MOV R4,R12
LDMFD R13!,{PC}

.plotveneer
STMFD R13!,{R10-R12,R14}
LDR R12,varstr
BL plotswi
LDMFD R13!,{R10-R12,PC}

.clearveneer
STMFD R13!,{R10-R12,R14}
LDR R12,varstr
BL clearwindowswi
LDMFD R13!,{R10-R12,PC}

.bankveneer
STMFD R13!,{R10-R12,R14}
LDR R12,varstr
BL setscreenbankswi
LDMFD R13!,{R10-R12,PC}
.varstr
DCD 0

.setbackdropswi
STMFD R13!,{R0,R14}
ADD R0,R0,R0,LSL #8
ADD R0,R0,R0,LSL #16
STR R0,[R12,#v.backdropstr]
LDMFD R13!,{R0,PC}

.setflashswi
STMFD R13!,{R0,R14}
ADD R0,R0,R0,LSL #8
ADD R0,R0,R0,LSL #16
STR R0,[R12,#v.flashstr]
LDMFD R13!,{R0,PC}

.setscreenbankswi
STMFD R13!,{R1-R2,R14}
LDR R1,[R12,#v.screenstart]
LDR R2,[R12,#v.modesize]
CMP R0,#1
ADDEQ R1,R1,R2
CMP R0,#&8000
MOVGE R1,R0
STR R1,[R12,#v.screenuse]
LDMFD R13!,{R1-R2,PC}

.clearwindowswi
STMFD R13!,{R1-R9,R14}
LDR R10,[R12,#v.screenuse]
LDR R2,[R12,#v.hbytes]
LDR R1,[R12,#v.cminy]
MUL R0,R1,R2
ADD R11,R10,R0
LDR R0,[R12,#v.cminx]
CMP R0,#0
LDREQ R0,[R12,#v.cmaxx]
CMPEQ R0,R2

BEQ clearblast
LDR R0,[R12,#v.cmaxx]
ANDS R0,R0,#3
LDREQ R0,[R12,#v.cminx]
ANDEQS R0,R0,#3
BEQ almostblast
STMFD R13!,{R10,R11}
LDR R0,[R12,#v.cmaxy]


MUL R9,R2,R0
ADD R9,R10,R9

LDR R0,[R12,#v.cminx]
LDR R1,[R12,#v.cmaxx]

ADD R10,R11,R1
ADD R11,R11,R0
LDR R0,[R12,#v.backdropstr]
.loop16
STRB R0,[R11]
STRB R0,[R11,#1]
STRB R0,[R11,#2]

STRB R0,[R10,#-1]
STRB R0,[R10,#-2]
STRB R0,[R10,#-3]
ADD R10,R10,R2
ADD  R11,R11,R2
CMP R10,R9
BLE loop16

LDMFD R13!,{R10,R11}
LDR R0,[R12,#v.cmaxy]
LDR R1,[R12,#v.cminy]
SUB R8,R0,R1
MUL R0,R2,R0
ADD R9,R10,R0
LDR R0,[R12,#v.cminx]
ADD R0,R0,#3
BIC R0,R0,#3
ADD R11,R11,R0
LDR R1,[R12,#v.cmaxx]
BIC R1,R1,#3
CMP R1,R0
BGT almostinsert
LDMFD R13!,{R1-R9,PC}

.almostblast
LDR R0,[R12,#v.cmaxy]
SUB R8,R0,R1
MUL R0,R2,R0
ADD R9,R10,R0
LDR R0,[R12,#v.cminx]
ADD R11,R11,R0
LDR R1,[R12,#v.cmaxx]
.almostinsert
SUB R8,R1,R0
CMP R8,#640
LDMHIFD R13!,{R1-R9,R14}
BHI toowideerr
RSB R8,R8,#640
SUB R1,R2,R1
ADD R10,R0,R1
LDR R0,[R12,#v.backdropstr]
MOV R1,R0
MOV R2,R0
MOV R3,R0
MOV R4,R0
MOV R5,R0
MOV R6,R0
MOV R7,R0
.loop15
AND R12,R8,#&3E0

ADD PC,PC,R12,LSR #3
MOV R0,R0
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
STMIA R11!,{R0-R7}
AND R12,R8,#&1C
ADD PC,PC,R12
MOV R0,R0
STR R1,[R11],#4
STR R1,[R11],#4
STR R1,[R11],#4
STR R1,[R11],#4
STR R1,[R11],#4
STR R1,[R11],#4
STR R1,[R11],#4
STR R1,[R11],#4
ADD R11,R11,R10
CMP R11,R9
BLT loop15
LDMFD R13!,{R1-R9,PC}




.clearblast

LDR R1,[R12,#v.cmaxy]
MUL R0,R1,R2
ADD R10,R10,R0
LDR R0,[R12,#v.backdropstr]
MOV R1,R0
MOV R2,R0
MOV R3,R0
MOV R4,R0
MOV R5,R0
MOV R6,R0
MOV R7,R0
MOV R8,R0
MOV R9,R0

SUB R0,R10,R11
CMP R0,#40*10
BLE loop13
.loop12
LDR R0,[R12,#v.backdropstr]
STMIA R11!,{R0-R9}
STMIA R11!,{R0-R9}
STMIA R11!,{R0-R9}
STMIA R11!,{R0-R9}
STMIA R11!,{R0-R9}
STMIA R11!,{R0-R9}
STMIA R11!,{R0-R9}
STMIA R11!,{R0-R9}
STMIA R11!,{R0-R9}
STMIA R11!,{R0-R9}
SUB R0,R10,R11
CMP R0,#40*10
BGT loop12
CMP R0,#36
BLE loop14
.loop13
STMIA R11!,{R1-R9}
SUB R0,R10,R11
CMP R0,#36
BGT loop13

.loop14
CMP R10,R11
LDMEQFD R13!,{R1-R9,PC}
STRB R1,[R11],#1
B loop14

.idbyte1
DCB "FSP1"
.idbyte2
DCB "FSP2"

.nodata    ;kept out of plot path
LDMFD R13!,{R1-R9,R14}
B nodataerr

.toobig    ;kept out of plot path
LDMFD R13!,{R1-R9,R14}
B toobigerr

.slotempty
LDMFD R13!,{R1-R9,R14}
ORR R14,R14,#1<<29; set carry
MOVS PC,R14

.readsizeswi
STMFD R13!,{R2-R11,R14}
MOV R4,R0
MOV R0,R0,LSR #24
BL getpoolpointerswi
MOV R10,R0
LDR R10,[R10]
BIC R10,R10,#3
BIC R0,R4,#&FF<<24
LDR R1,[R10]
ADR R2,idbyte1
LDMIA R2,{R3,R4}
CMP R1,R3
BEQ fsp1size
CMP R1,R4
BNE sizenodata	;drops through

.fsp2size
LDR R1,[R10,#4]
BIC R3,R0,#&FF<<16
CMP R1,R3
CMNGT R3,#1
BLE sizetoobig
ADD R3,R3,#3               ;get sprite block offset
LDR R3,[R10,R3,LSL #2]
CMP R3,#0
BEQ sizeslotempty
AND R4,R3,#&FF
AND R4,R4,R0,LSR #16
ADD R3,R3,R4,LSL #12
LDR R4,[R10,R3,LSR #8]
LDR R0,[R10,R4,LSR #8]
BIC R1,R0,#&FF<<24
BIC R1,R1 #&FF<<16         ;y size
MOV R0,R0,LSR #16          ;x size
LDMFD R13!,{R2-R11,PC}^

.fsp1size

LDR R1,[R10,#12]
CMP R1,R0
CMNGT R0,#1
BLE sizetoobig
ADD R0,R0,#4               ;get sprite block offset
LDR R0,[R10,R0,LSL #2]
CMP R0,#0
BEQ sizeslotempty
LDR R1,[R10,R0]!

AND R0,R1,#&FF            ;x size
AND R1,R1,#&FF<<8         ;y size - R7,R8 -- sprite width, height
MOV R1,R1,LSR #8
LDMFD R13!,{R2-R11,PC}^

.sizenodata
LDMFD R13!,{R2-R11,R14}
B nodataerr

.sizetoobig
LDMFD R13!,{R2-R11,R14}
B toobigerr

.sizeslotempty
MOV R0,#0
MOV R1,#0
LDMFD R13!,{R2-R11,PC}^



.plotswi
BIC R14,R14,#&0f<<28; clear flags for return
STMFD R13!,{R1-R9,R14}
AND R6,R0,#&3F<<24
BIC R0,R0,#&FF<<24
ADD R10,R12,#v.startblock
ADD R10,R10,R6,LSR #22
CMP R6,#0
ADDEQ R10,R12,#v.datastart
LDR R10,[R10]
BIC R10,R10,#3; mask out flag bits
LDR R7,[R10]
ADR R6,idbyte1
LDMIA R6,{R8,R9}
CMP R7,R8
BEQ fsp1plot
CMP R7,R9
BNE nodata
		;drops through
.fsp2plot

LDR R9,[R10,#4]
BIC R3,R0,#&FF<<16
CMP R9,R3
CMNGT R3,#1
BLE toobig
ADD R3,R3,#3               ;get sprite block offset
LDR R3,[R10,R3,LSL #2]
CMP R3,#0
BEQ slotempty
AND R4,R3,#&FF      ; get frame limit
AND R4,R4,R0,LSR #16; get animation frame
ADD R3,R3,R4,LSL #12 ; 
LDR R4,[R10,R3,LSR #8]     ; get address of sprite to plot
ADD R4,R10,R4,LSR #8

LDMIA R4,{R8,R9}
AND R0,R1,#3
SUB R1,R1,R9,ASR #16       ;x ofs
MOV R9,R9,ASL #16
SUB R2,R2,R9,ASR #16       ;y ofs
ADD R3,R3,R0,LSL #10
LDR R3,[R10,R3,LSR #8]
ADD R10,R10,R3,LSR #8
TST R3,#4
SUBNE R1,R1,#4
TST R3,#8
BICEQ R1,R1,#3               ;align R1 as for h-locks
ANDEQ R3,R3,#3
ORREQ R1,R1,R3               ;R3 & 3 contains the bits that we expect in the
                           ;low order of R11


LDR R11,[R12,#v.screenuse] ;get screen address
LDR R9,[R12,#v.hbytes]
MUL R0,R9,R2
ADD R11,R11,R0
ADD R11,R11,R1

BIC R9,R8,#&FF<<24
BIC R9,R9 #&FF<<16         ;y size
MOV R8,R8,LSR #16          ;x size

ADD R0,R12,#v.cminx
LDMIA R0,{R3-R6}           ;get clip margins pronto
                           ;R3,R4,R5,R6 -- min x,min y, max x, max y
SUB R5,R5,R8
SUB R6,R6,R9
CMP R1,R3
CMPGE R2,R4
CMPGE R5,R1
CMPGE R6,R2
MOVGE R8,#0
MOV R7,#0
BGE fsp2fullon             ;fully on screen, so go for it
LDMIA R0,{R3-R6}           ;again
SUB R3,R3,R8               ;checking for completely off screen
SUB R4,R4,R9
CMP R1,R3
CMPGT R2,R4
CMPGT R5,R1
CMPGT R6,R2
LDMLEFD R13!,{R1-R9,PC}^   ;fully off screen
LDMIA R0,{R3-R4}
            
SUB R0,R6,R9
CMP R2,R0            	;bottom clip
 SUBGT R9,R6,R2
CMP R2,R4               ;top clip
SUB R0,R5,R8            ;squeezed in - part of horiz.clip
MOV R8,#0               ;ditto
 SUBLT R8,R4,R2

CMP R1,R0
 SUBGE R7,R5,R1         ;right clip

CMP R1,R3
 SUBLT R0,R3,R1         ;left clip

 ADDLT R7,R7,R0,ASL #16
.fsp2fullon
LDR R0,[R10,#8]
CMP R0,#0
BLNE stmblast
LDR R0,[R10,#12]
CMP R0,#0
BLNE strblast
LDR R0,[R10,#16]
CMP R0,#0
BNE strbpaint
LDMFD R13!,{R1-R9,PC}^

.fsp1plot

LDR R9,[R10,#12]
CMP R9,R0
CMNGT R0,#1
BLE toobig
ADD R0,R0,#4               ;get sprite block offset
LDR R0,[R10,R0,LSL #2]
CMP R0,#0
BEQ slotempty
LDR R11,[R10,R0]!          ;Move by offsets - remember byte order
AND R0,R11,#&FF<<16        ;x ofs
SUB R1,R1,R0,LSR #16
AND R0,R11,#&FF<<24        ;y ofs
SUB R2,R2,R0,LSR #24       ;R1,R2 -- x,y coord of top left corner

AND R8,R11,#&FF            ;x size
AND R9,R11,#&FF<<8         ;y size - R7,R8 -- sprite width, height
MOV R9,R9,LSR #8

LDR R11,[R12,#v.screenuse] ;get screen address
LDR R0,[R12,#v.hbytes]
MUL R0,R2,R0
ADD R11,R11,R0
ADD R11,R11,R1

ADD R0,R12,#v.cminx
LDMIA R0,{R3-R6}           ;get clip margins pronto
                           ;R3,R4,R5,R6 -- min x,min y, max x, max y
SUB R5,R5,R8
SUB R6,R6,R9
CMP R1,R3
CMPGE R2,R4
CMPGE R5,R1
CMPGE R6,R2
MOVGE R8,#0
MOV R7,#0  ;right/left clip indicator
BGE fsp1fullon             ;fully on screen, so go for it

LDMIA R0,{R3-R6}           ;again
SUB R3,R3,R8               ;checking for completely off screen
SUB R4,R4,R9
CMP R1,R3
CMPGT R2,R4
CMPGT R5,R1
CMPGT R6,R2
LDMLEFD R13!,{R1-R9,PC}^   ;fully off screen
LDMIA R0,{R3-R4}
            
SUB R0,R6,R9
CMP R2,R0            	;bottom clip
 SUBGT R9,R6,R2
CMP R2,R4               ;top clip
SUB R0,R5,R8            ;squeezed in - part of horiz.clip
MOV R8,#0               ;ditto
 SUBLT R8,R4,R2

CMP R1,R0
 SUBGE R7,R5,R1         ;right clip
CMP R1,R3
 SUBLT R0,R3,R1         ;left clip
 ADDLT R7,R7,R0,ASL #16
.fsp1fullon
.fsp1blast
ADD R8,R8,#1
ADD R9,R9,#1
CMP R7,#0
BNE fsp1rightclip
B blastins
.strbpaint
			;drops through
.blast
ADD R10,R10,R0,LSR #8
CMP R7,#0
BNE rightclip
.blastins
LDR R8,[R10,R8,LSL #2]
LDR R9,[R10,R9,LSL #2]
CMP R9,R8
LDMLEFD R13!,{R1-R9,PC}^
ADD R9,R10,R9
ADD R10,R10,R8

.loop2
SUB R12,R9,R10
CMP R12,#22<<2
BLT skip1
.loop3
LDMIA R10!,{R0-R8,R12,R14}
STRB R0,[R11,R0,LSR #8]
STRB R1,[R11,R1,LSR #8]
STRB R2,[R11,R2,LSR #8]
STRB R3,[R11,R3,LSR #8]
STRB R4,[R11,R4,LSR #8]
STRB R5,[R11,R5,LSR #8]
STRB R6,[R11,R6,LSR #8]
STRB R7,[R11,R7,LSR #8]
STRB R8,[R11,R8,LSR #8]
STRB R12,[R11,R12,LSR #8]
STRB R14,[R11,R14,LSR #8]
.loop1
LDMIA R10!,{R0-R8,R12,R14}
STRB R0,[R11,R0,LSR #8]
STRB R1,[R11,R1,LSR #8]
STRB R2,[R11,R2,LSR #8]
STRB R3,[R11,R3,LSR #8]
STRB R4,[R11,R4,LSR #8]
STRB R5,[R11,R5,LSR #8]
STRB R6,[R11,R6,LSR #8]
STRB R7,[R11,R7,LSR #8]
STRB R8,[R11,R8,LSR #8]
STRB R12,[R11,R12,LSR #8]
STRB R14,[R11,R14,LSR #8]
SUB R12,R9,R10
CMP R12,#22<<2
BGE loop3
.skip1
CMP R12,#11<<2
BGE loop1
LDMIA R10!,{R0-R8,R14}
RSB R12,R12,#10<<2
ADD PC,PC,R12
MOV R0,R0
STRB R14,[R11,R14,LSR #8]
STRB R8,[R11,R8,LSR #8]
STRB R7,[R11,R7,LSR #8]
STRB R6,[R11,R6,LSR #8]
STRB R5,[R11,R5,LSR #8]
STRB R4,[R11,R4,LSR #8]
STRB R3,[R11,R3,LSR #8]
STRB R2,[R11,R2,LSR #8]
STRB R1,[R11,R1,LSR #8]
STRB R0,[R11,R0,LSR #8]

.offscrn
LDMFD R13!,{R1-R9,PC}^


.fsp1rightclip
CMP R7,#&10000
BGE fsp1leftclip
LDR R0,[R12,#v.hbytes]
MUL R1,R8,R0
SUB R1,R1,R0
B rightclipins

.rightclip
CMP R7,#&10000
BGE leftclip
LDR R0,[R12,#v.hbytes]
MUL R1,R8,R0    ;R8 = top line to plot
		;R9 = bottom line to plot
                ;R7 = positon to clip on right
.rightclipins
ADD R5,R7,R1    
MOV R14,R5,LSL #8  ;create threshold for clip
LDR R7,[R10,R8,LSL #2] ;indirect via vertical clipping offsets
ADD R7,R10,R7
.loop5
MOV R6,R7		; retrieve R6 from previous R7
ADD R8,R8,#1
LDR R7,[R10,R8,LSL #2]
ADD R7,R10,R7  		;translate to read positions
CMP R8,R9
LDMGTFD R13!,{R1-R9,PC}^  ;finished
CMP R6,R7		; nothing on this line
ADDGE R14,R14,R0,LSL #8
BGE loop5

SUB R0,R7,R6
CMP R0,#12<<2
BLT rightskip

.loop6
LDMIA R6!,{R0-R5}
CMP R14,R0
STRGEB R0,[R11,R0,LSR #8]
CMP R14,R1
STRGEB R1,[R11,R1,LSR #8]
CMP R14,R2
STRGEB R2,[R11,R2,LSR #8]
CMP R14,R3
STRGEB R3,[R11,R3,LSR #8]
CMP R14,R4
STRGEB R4,[R11,R4,LSR #8]
CMP R14,R5
STRGEB R5,[R11,R5,LSR #8]
BLT rightclipnextline
.loop4
LDMIA R6!,{R0-R5}
CMP R14,R0
STRGEB R0,[R11,R0,LSR #8]
CMP R14,R1
STRGEB R1,[R11,R1,LSR #8]
CMP R14,R2
STRGEB R2,[R11,R2,LSR #8]
CMP R14,R3
STRGEB R3,[R11,R3,LSR #8]
CMP R14,R4
STRGEB R4,[R11,R4,LSR #8]
CMP R14,R5
STRGEB R5,[R11,R5,LSR #8]
BLT rightclipnextline
SUB R0,R7,R6
CMP R0,#12<<2
BGE loop6

.rightskip
CMP R0,#6<<2
BGE loop4
SUB R5,R7,R6
LDMIA R6!,{R0-R4}
RSBS R5,R5,#5<<2
ADDNE PC,PC,R5,LSL #1
MOV R0,R0
CMP R14,R4
STRGEB R4,[R11,R4,LSR #8]
CMP R14,R3
STRGEB R3,[R11,R3,LSR #8]
CMP R14,R2
STRGEB R2,[R11,R2,LSR #8]
CMP R14,R1
STRGEB R1,[R11,R1,LSR #8]
CMP R14,R0
STRGEB R0,[R11,R0,LSR #8]

.rightclipnextline
LDR R0,[R12,#v.hbytes]
ADD R14,R14,R0,LSL #8
B loop5


.fsp1leftclip
TST R7,#&FF
TSTEQ R7,#&FF<<8
BNE fsp1fullclip
LDR R0,[R12,#v.hbytes]
MUL R1,R8,R0
SUB R1,R1,R0
B leftclipins

.leftclip
TST R7,#&FF
TSTEQ R7,#&FF<<8
BNE fullclip
LDR R0,[R12,#v.hbytes]
MUL R1,R8,R0    ;R8 = top line to plot
		;R9 = bottom line to plot
                ;R7 = positon to clip on left
.leftclipins
MOV R7,R7,LSR #16
ADD R5,R7,R1    
MOV R14,R5,LSL #8  ;create threshold for clip
.loop7
LDR R6,[R10,R8,LSL #2]
ADD R6,R10,R6
ADD R8,R8,#1
LDR R7,[R10,R8,LSL #2]
ADD R7,R10,R7  		;translate to read positions
CMP R8,R9
LDMGTFD R13!,{R1-R9,PC}^  ;finished
CMP R6,R7		; nothing on this line
ADDGE R14,R14,R0,LSL #8
BGE loop7

SUB R0,R7,R6
CMP R0,#12<<2
BLT leftskip

.loop8
LDMDB R7!,{R0-R5}
CMP R14,R0
STRLEB R0,[R11,R0,LSR #8]
CMP R14,R1
STRLEB R1,[R11,R1,LSR #8]
CMP R14,R2
STRLEB R2,[R11,R2,LSR #8]
CMP R14,R3
STRLEB R3,[R11,R3,LSR #8]
CMP R14,R4
STRLEB R4,[R11,R4,LSR #8]
CMP R14,R5
STRLEB R5,[R11,R5,LSR #8]
BGT leftclipnextline
.loop9
LDMDB R7!,{R0-R5}
CMP R14,R0
STRLEB R0,[R11,R0,LSR #8]
CMP R14,R1
STRLEB R1,[R11,R1,LSR #8]
CMP R14,R2
STRLEB R2,[R11,R2,LSR #8]
CMP R14,R3
STRLEB R3,[R11,R3,LSR #8]
CMP R14,R4
STRLEB R4,[R11,R4,LSR #8]
CMP R14,R5
STRLEB R5,[R11,R5,LSR #8]
BGT leftclipnextline
SUB R0,R7,R6
CMP R0,#12<<2
BGE loop8

.leftskip
CMP R0,#6<<2
BGE loop9
SUB R5,R7,R6
LDMDB R7!,{R0-R4}
RSBS R5,R5,#5<<2
ADDGT PC,PC,R5,LSL #1
MOV R0,R0
CMP R14,R0
STRLEB R0,[R11,R0,LSR #8]
CMP R14,R1
STRLEB R1,[R11,R1,LSR #8]
CMP R14,R2
STRLEB R2,[R11,R2,LSR #8]
CMP R14,R3
STRLEB R3,[R11,R3,LSR #8]
CMP R14,R4
STRLEB R4,[R11,R4,LSR #8]

.leftclipnextline
LDR R0,[R12,#v.hbytes]
ADD R14,R14,R0,LSL #8
B loop7

.fsp1fullclip
LDR R0,[R12,#v.hbytes]
MUL R1,R8,R0
SUB R1,R1,R0
B fullclipins

.fullclip
LDR R0,[R12,#v.hbytes]
MUL R1,R8,R0    ;R8 = top line to plot
		;R9 = bottom line to plot
                ;R7 = positon to clip on right
.fullclipins
MOV R6,R7,LSR #16
BIC R7,R7,#&FFFF<<16
ADD R5,R7,R1
    
MOV R14,R5,LSL #8  ;create threshold for clip
ADD R5,R6,R1
MOV R5,R5,LSL #8
LDR R7,[R10,R8,LSL #2] ;indirect via vertical clipping offsets
ADD R7,R10,R7
.loop55
MOV R6,R7		; retrieve R6 from previous R7
ADD R8,R8,#1
LDR R7,[R10,R8,LSL #2]
ADD R7,R10,R7  		;translate to read positions
CMP R8,R9
LDMGTFD R13!,{R1-R9,PC}^  ;finished
CMP R6,R7		; nothing on this line
ADDGE R14,R14,R0,LSL #8
ADDGE R5,R5,R0,LSL #8
BGE loop55

SUB R0,R7,R6
CMP R0,#10<<2
BLT fullskip

.loop56
LDMIA R6!,{R0-R4}
CMP R14,R0
CMPGE R0,R5
STRGEB R0,[R11,R0,LSR #8]
CMP R14,R1
CMPGE R1,R5
STRGEB R1,[R11,R1,LSR #8]
CMP R14,R2
CMPGE R2,R5
STRGEB R2,[R11,R2,LSR #8]
CMP R14,R3
CMPGE R3,R5
STRGEB R3,[R11,R3,LSR #8]
CMP R14,R4
CMPGE R4,R5
STRGEB R4,[R11,R4,LSR #8]
BLT fullclipnextline
.loop54
LDMIA R6!,{R0-R4}
CMP R14,R0
CMPGE R0,R5
STRGEB R0,[R11,R0,LSR #8]
CMP R14,R1
CMPGE R1,R5
STRGEB R1,[R11,R1,LSR #8]
CMP R14,R2
CMPGE R2,R5
STRGEB R2,[R11,R2,LSR #8]
CMP R14,R3
CMPGE R3,R5
STRGEB R3,[R11,R3,LSR #8]
CMP R14,R4
CMPGE R4,R5
STRGEB R4,[R11,R4,LSR #8]
BLT fullclipnextline
SUB R0,R7,R6
CMP R0,#10<<2
BGE loop56

.fullskip
CMP R0,#5<<2
BGE loop54
SUB R4,R7,R6
LDMIA R6!,{R0-R3}

CMP R4,#4<<2
CMPGE R14,R3
CMPGE R3,R5
STRGEB R3,[R11,R3,LSR #8]
CMP R4,#3<<2
CMPGE R14,R2
CMPGE R2,R5
STRGEB R2,[R11,R2,LSR #8]
CMP R4,#2<<2
CMPGE R14,R1
CMPGE R1,R5
STRGEB R1,[R11,R1,LSR #8]
CMP R4,#1<<2
CMPGE R14,R0
CMPGE R0,R5
STRGEB R0,[R11,R0,LSR #8]

.fullclipnextline
LDR R0,[R12,#v.hbytes]
ADD R14,R14,R0,LSL #8
ADD R5,R5,R0,LSL #8
B loop55



.strblast
STMFD R13!,{R6-R11,R14}
ADD R10,R10,R0,LSR #8
CMP R7,#0
BNE strrightclip
LDMNEFD R13!,{R6-R11,PC}^
LDR R8,[R10,R8,LSL #2]
LDR R9,[R10,R9,LSL #2]
CMP R9,R8
LDMLEFD R13!,{R6-R11,PC}^
ADD R9,R10,R9
ADD R10,R10,R8
SUB R0,R9,R10
CMP R0,#4*32
BLT strskip

.loop36
LDMIA R10!,{R0-R7}
STR R1,[R11,R0,LSR #8]
STR R3,[R11,R2,LSR #8]
STR R5,[R11,R4,LSR #8]
STR R7,[R11,R6,LSR #8]
LDMIA R10!,{R0-R7}
STR R1,[R11,R0,LSR #8]
STR R3,[R11,R2,LSR #8]
STR R5,[R11,R4,LSR #8]
STR R7,[R11,R6,LSR #8]
.loop37
LDMIA R10!,{R0-R7}
STR R1,[R11,R0,LSR #8]
STR R3,[R11,R2,LSR #8]
STR R5,[R11,R4,LSR #8]
STR R7,[R11,R6,LSR #8]
LDMIA R10!,{R0-R7}
STR R1,[R11,R0,LSR #8]
STR R3,[R11,R2,LSR #8]
STR R5,[R11,R4,LSR #8]
STR R7,[R11,R6,LSR #8]
SUB R0,R9,R10
CMP R0,#4*32
BGE loop36
.strskip
CMP R0,#2*32
BGE loop37
CMP R0,#32
LDMGEIA R10!,{R0-R7}
STRGE R1,[R11,R0,LSR #8]
STRGE R3,[R11,R2,LSR #8]
STRGE R5,[R11,R4,LSR #8]
STRGE R7,[R11,R6,LSR #8]
SUB R9,R9,R10
LDMIA R10!,{R0-R7}
CMP R9,#8
STRGE R1,[R11,R0,LSR #8]
CMP R9,#16
STRGE R3,[R11,R2,LSR #8]
CMP R9,#24
STRGE R5,[R11,R4,LSR #8]
CMP R9,#32
STRGE R7,[R11,R6,LSR #8]
LDMFD R13!,{R6-R11,PC}^

.strrightclip
CMP R7,#&10000
BGE strleftclip
LDR R0,[R12,#v.hbytes]
MUL R1,R8,R0    ;R8 = top line to plot
		;R9 = bottom line to plot
                ;R7 = positon to clip on right
ADD R14,R7,R1
MOV R14,R14,LSL #8
LDR R7,[R10,R8,LSL #2] ;indirect via vertical clipping offsets
ADD R7,R10,R7

.loop40
MOV R6,R7		; retrieve R6 from previous R7
ADD R8,R8,#1
LDR R7,[R10,R8,LSL #2]
ADD R7,R10,R7           ;translate to a read position
CMP R8,R9
LDMGTFD R13!,{R6-R11,PC}^  ;finished
CMP R6,R7		; nothing on this line
ADDGE R14,R14,R0,LSL #8
BGE loop40
SUB R0,R7,R6
CMP R0,#12*8
BLT strrightskip
.loop41
LDMIA R6!,{R0-R5}
CMP R0,R14
STRLT R1,[R11,R0,LSR #8]
CMP R2,R14
STRLT R3,[R11,R2,LSR #8]
CMP R4,R14
STRLT R5,[R11,R4,LSR #8]
LDMIA R6!,{R0-R5}
CMP R0,R14
STRLT R1,[R11,R0,LSR #8]
CMP R2,R14
STRLT R3,[R11,R2,LSR #8]
CMP R4,R14
STRLT R5,[R11,R4,LSR #8]
.loop42
LDMIA R6!,{R0-R5}
CMP R0,R14
STRLT R1,[R11,R0,LSR #8]
CMP R2,R14
STRLT R3,[R11,R2,LSR #8]
CMP R4,R14
STRLT R5,[R11,R4,LSR #8]
.loop43
LDMIA R6!,{R0-R5}
CMP R0,R14
STRLT R1,[R11,R0,LSR #8]
CMP R2,R14
STRLT R3,[R11,R2,LSR #8]
CMP R4,R14
STRLT R5,[R11,R4,LSR #8]
SUB R0,R7,R6
CMP R0,#12*8
BGE loop41

.strrightskip
CMP R0,#6*8
BGE loop42
CMP R0,#3*8
BGE loop43
RSB R5,R0,#2*8
LDMIA R6!,{R0-R3}
CMP R5,#1*8+1
CMPLT R0,R14
STRLT R1,[R11,R0,LSR #8]
CMPLT R5,#0*8+1
CMPLT R2,R14
STRLT R3,[R11,R2,LSR #8]
.strrightnextline
LDR R0,[R12,#v.hbytes]
ADD R14,R14,R0,LSL #8
B loop40


.strleftclip
TST R7,#&FF
TSTEQ R7,#&FF<<8
BNE strfullclip
LDR R0,[R12,#v.hbytes]
MUL R1,R8,R0    ;R8 = top line to plot
		;R9 = bottom line to plot
                ;R7 = positon to clip on right
MOV R7,R7,LSR #16
ADD R14,R7,R1
MOV R14,R14,LSL #8

.loop44
LDR R6,[R10,R8,LSL #2]		; retrieve R6 from previous R7
ADD R6,R10,R6
ADD R8,R8,#1
LDR R7,[R10,R8,LSL #2]
ADD R7,R10,R7           ;translate to a read position
CMP R8,R9
LDMGTFD R13!,{R6-R11,PC}^  ;finished
CMP R6,R7		; nothing on this line
ADDGE R14,R14,R0,LSL #8
BGE loop44
SUB R0,R7,R6
CMP R0,#12*8
BLT strleftskip
.loop45
LDMDB R7!,{R0-R5}
CMP R14,R0
STRLT R1,[R11,R0,LSR #8]
CMP R14,R2
STRLT R3,[R11,R2,LSR #8]
CMP R14,R4
STRLT R5,[R11,R4,LSR #8]
LDMDB R7!,{R0-R5}
CMP R14,R0
STRLT R1,[R11,R0,LSR #8]
CMP R14,R2
STRLT R3,[R11,R2,LSR #8]
CMP R14,R4
STRLT R5,[R11,R4,LSR #8]
.loop46
LDMDB R7!,{R0-R5}
CMP R14,R0
STRLT R1,[R11,R0,LSR #8]
CMP R14,R2
STRLT R3,[R11,R2,LSR #8]
CMP R14,R4
STRLT R5,[R11,R4,LSR #8]
.loop47
LDMDB R7!,{R0-R5}
CMP R14,R0
STRLT R1,[R11,R0,LSR #8]
CMP R14,R2
STRLT R3,[R11,R2,LSR #8]
CMP R14,R4
STRLT R5,[R11,R4,LSR #8]
SUB R0,R7,R6
CMP R0,#12*8
BGE loop45

.strleftskip
CMP R0,#6*8
BGE loop46
CMP R0,#3*8
BGE loop47
RSB R5,R0,#2*8
LDMDB R7!,{R0-R3}
CMP R5,#1*8+1
CMPLT R14,R2
STRLT R3,[R11,R2,LSR #8]
CMPLT R5,#0*8+1
CMPLT R14,R0
STRLT R1,[R11,R0,LSR #8]
.strleftnextline
LDR R0,[R12,#v.hbytes]
ADD R14,R14,R0,LSL #8
B loop44

.strfullclip
MOV R6,R7,LSR #16
BIC R7,R7,#&FFFF<<16
LDR R0,[R12,#v.hbytes]
MUL R1,R8,R0    ;R8 = top line to plot
		;R9 = bottom line to plot
                ;R7 = positon to clip on right
ADD R14,R7,R1
ADD R5,R6,R1
MOV R14,R14,LSL #8
MOV R5,R5,LSL #8
LDR R7,[R10,R8,LSL #2] ;indirect via vertical clipping offsets
ADD R7,R10,R7

.loop52
MOV R6,R7		; retrieve R6 from previous R7
ADD R8,R8,#1
LDR R7,[R10,R8,LSL #2]
ADD R7,R10,R7           ;translate to a read position
CMP R8,R9
LDMGTFD R13!,{R6-R11,PC}^  ;finished
CMP R6,R7		; nothing on this line
ADDGE R14,R14,R0,LSL #8
ADDGE R5,R5,R0,LSL #8
BGE loop52
SUBS R0,R7,R6
CMP R0,#4*4
BLT strfullskip
.loop53

LDMIA R6!,{R0-R3}
CMP R0,R14
CMPLT R5,R0
STRLT R1,[R11,R0,LSR #8]
CMP R2,R14
CMPLT R5,R2
STRLT R3,[R11,R2,LSR #8]
SUB R0,R7,R6
CMP R0,#4*4
BGE loop53

.strfullskip
CMP R0,#2*4
BLT strfullnextline
LDMIA R6!,{R0-R1}
CMP R0,R14
CMPLT R5,R0
STRLT R1,[R11,R0,LSR #8]

.strfullnextline
LDR R0,[R12,#v.hbytes]
ADD R14,R14,R0,LSL #8
ADD R5,R5,R0,LSL #8
B loop52


.stmblast
STMFD R13!,{R6-R11,R14}
ADD R10,R10,R0,LSR #8
CMP R7,#0
BNE stmrightclip
LDR R8,[R10,R8,LSL #2]
LDR R9,[R10,R9,LSL #2]
CMP R9,R8
LDMLEFD R13!,{R6-R11,PC}^
ADD R9,R10,R9
ADD R10,R10,R8
SUB R0,R9,R10
CMP R0,#4*32
BLT stmskip
.loop24
LDMIA R10,{R0-R7}
AND R14,R0,#&C
ADD R10,R10,R14,LSL #2
ADD R0,R11,R0,LSR #8
CMP R14,#8
STMEQIA R0,{R1-R7}
STMNEIA R0,{R1-R3}
LDMIA R10,{R0-R7}
AND R14,R0,#&C
ADD R10,R10,R14,LSL #2
ADD R0,R11,R0,LSR #8
CMP R14,#8
STMEQIA R0,{R1-R7}
STMNEIA R0,{R1-R3}
.loop28
LDMIA R10,{R0-R7}
AND R14,R0,#&C
ADD R10,R10,R14,LSL #2
ADD R0,R11,R0,LSR #8
CMP R14,#8
STMEQIA R0,{R1-R7}
STMNEIA R0,{R1-R3}
LDMIA R10,{R0-R7}
AND R14,R0,#&C
ADD R10,R10,R14,LSL #2
ADD R0,R11,R0,LSR #8
CMP R14,#8
STMEQIA R0,{R1-R7}
STMNEIA R0,{R1-R3}
SUB R0,R9,R10
CMP R0,#4*32
BGE loop24
CMP R0,#2*32
BGE loop28
.stmskip
.loop27
CMP R10,R9
LDMGEFD R13!,{R6-R11,PC}^
LDMIA R10,{R0-R7}
AND R14,R0,#&C
ADD R10,R10,R14,LSL #2
ADD R0,R11,R0,LSR #8
CMP R14,#8
STMEQIA R0,{R1-R7}
STMNEIA R0,{R1-R3}
CMP R10,R9
LDMGEFD R13!,{R6-R11,PC}^
LDMIA R10,{R0-R7}
AND R14,R0,#&C
ADD R10,R10,R14,LSL #2
ADD R0,R11,R0,LSR #8
CMP R14,#8
STMEQIA R0,{R1-R7}
STMNEIA R0,{R1-R3}
CMP R10,R9
LDMGEFD R13!,{R6-R11,PC}^
LDMIA R10,{R0-R7}
AND R14,R0,#&C
ADD R10,R10,R14,LSL #2
ADD R0,R11,R0,LSR #8
CMP R14,#8
STMEQIA R0,{R1-R7}
STMNEIA R0,{R1-R3}
CMP R10,R9
LDMGEFD R13!,{R6-R11,PC}^
LDMIA R10,{R0-R7}
AND R14,R0,#&C
ADD R10,R10,R14,LSL #2
ADD R0,R11,R0,LSR #8
CMP R14,#8
STMEQIA R0,{R1-R7}
STMNEIA R0,{R1-R3}
B loop27

.stmrightclip
CMP R7,#&10000
BGE stmleftclip
LDR R0,[R12,#v.hbytes]
MUL R1,R8,R0    ;R8 = top line to plot
		;R9 = bottom line to plot
                ;R7 = positon to clip on right
ADD R5,R7,R1
BIC R5,R5,#3    ;word align
ADD R14,R11,R5      ;create threshold for clip
LDR R7,[R10,R8,LSL #2] ;indirect via vertical clipping offsets
ADD R7,R10,R7

.loop30
MOV R6,R7		; retrieve R6 from previous R7
ADD R8,R8,#1
LDR R7,[R10,R8,LSL #2]
ADD R7,R10,R7           ;translate to a read position
CMP R8,R9
LDMGTFD R13!,{R6-R11,PC}^  ;finished
CMP R6,R7		; nothing on this line
ADDGE R14,R14,R0
BGE loop30
.loop31
SUB R0,R7,R6
CMP R0,#0
BLE stmrightnextline
LDMIA R6!,{R0-R3}
AND R5,R0,#&C
ADD R0,R11,R0,LSR #8
SUBS R4,R14,R0
BMI loop31
CMP R5,#8
BEQ stmright8
CMP R4,#8
STMGTIA R0,{R1-R3}
BGT loop31
CMP R4,#4
STMGTIA R0,{R1-R2}
BGT loop31
CMP R4,#0
STRGT R1,[R0]
B loop31

.stmright8
CMP R4,#28
MOVGT R4,#28
ADD R4,R4,#3
AND R4,R4,#28
RSBS R4,R4,#28
ADDNE PC,PC,R4,LSL #2
MOV R0,R0

STMIA R0!,{R1-R3}
LDMIA R6!,{R1-R4}
STMIA R0,{R1-R4}
B loop31
STMIA R0!,{R1-R3}
LDMIA R6!,{R1-R4}
STMIA R0,{R1-R3}
B loop31
STMIA R0!,{R1-R3}
LDMIA R6!,{R1-R4}
STMIA R0,{R1-R2}
B loop31
STMIA R0!,{R1-R3}
LDMIA R6!,{R1-R4}
STR R1,[R0]
B loop31
STMIA R0!,{R1-R3}
ADD R6,R6,#16
B loop31
DCD &E6000090
STMIA R0!,{R1-R2}
ADD R6,R6,#16
B loop31
DCD &E6000090
STR R1,[R0]
ADD R6,R6,#16
B loop31
DCD &E6000090
ADD R6,R6,#16
B loop31

.stmrightnextline
LDR R0,[R12,#v.hbytes]
ADD R14,R14,R0
B loop30

.stmleftclip
TST R7,#&FF
TSTEQ R7,#&FF<<8
BNE stmfullclip
LDR R0,[R12,#v.hbytes]
MUL R1,R8,R0    ;R8 = top line to plot
		;R9 = bottom line to plot
                ;R7 = positon to clip on left
MOV R7,R7,ASR #16
ADD R7,R7,R1
ADD R14,R11,R7          ;create threshold for clip
LDR R7,[R10,R8,LSL #2]  ;indirect via vertical clipping offsets
ADD R7,R10,R7

.loop34
MOV R6,R7		; retrieve R6 from previous R7
ADD R8,R8,#1
LDR R7,[R10,R8,LSL #2]
ADD R7,R10,R7           ;translate to a read position
CMP R8,R9
LDMGTFD R13!,{R6-R11,PC}^  ;finished
CMP R6,R7		; nothing on this line
ADDGE R14,R14,R0
BGE loop34
.loop35
SUB R0,R7,R6
CMP R0,#0
BLE stmleftnextline
LDMIA R6!,{R0-R3}
AND R5,R0,#&C
CMP R5,#4
ADD R0,R11,R0,LSR #8
BGT stmleft8

CMP R0,R14
STMGEIA R0!,{R1-R3}
BGE loop35
SUB R5,R14,#8
CMP R0,R5
STRGE R3,[R0,#8]
SUB R5,R14,#4 
CMP R0,R5
STRGE R2,[R0,#4]
B loop35

.stmleft8
CMP R0,R14
STMGEIA R0!,{R1-R3}
LDMGEIA R6!,{R1-R4}
STMGEIA R0,{R1-R4}
BGE loop35
SUB R5,R14,#8
CMP R0,R5
STRGE R3,[R0,#8]
SUB R5,R14,#4
CMPGE R0,R5
STRGE R2,[R0,#4]     ;Will never have to store R1 here
LDMIA R6!,{R1-R4}
ADD R0,R0,#12
STMGEIA R0!,{R1-R4}
BGE loop35
SUB R5,R14,#12
CMP R0,R5
STRGE R4,[R0,#12]
SUB R5,R14,#8
CMP R0,R5
STRGE R3,[R0,#8]
SUB R5,R14,#4
CMPGE R0,R5
STRGE R2,[R0,#4]
CMPGE R0,R14
STRGE R1,[R0,#0]
B loop35
.stmleftnextline
LDR R0,[R12,#v.hbytes]
ADD R14,R14,R0
B loop34

.stmfullclip
MOV R6,R7,LSR #16
BIC R7,R7,#&FFFF<<16
LDR R0,[R12,#v.hbytes]
MUL R1,R8,R0    ;R8 = top line to plot
		;R9 = bottom line to plot
                ;R7 = positon to clip on right
ADD R5,R7,R1
BIC R5,R5,#3    ;word align
ADD R14,R11,R5      ;create threshold for clip
ADD R5,R6,R1
SUB R5,R5,#1
BIC R5,R5,#3
ADD R5,R11,R5

LDR R7,[R10,R8,LSL #2] ;indirect via vertical clipping offsets
ADD R7,R10,R7

.loop50
MOV R6,R7		; retrieve R6 from previous R7
ADD R8,R8,#1
LDR R7,[R10,R8,LSL #2]
ADD R7,R10,R7           ;translate to a read position
CMP R8,R9
LDMGTFD R13!,{R6-R11,PC}^  ;finished
CMP R6,R7		; nothing on this line
ADDGE R14,R14,R0
ADDGE R5,R5,R0
BGE loop50
.loop51
SUB R0,R7,R6
CMP R0,#0
BLE stmfullnextline
LDMIA R6!,{R0-R3}
AND R4,R0,#&C
ADD R0,R11,R0,LSR #8
CMP R0,R14
CMPLT R5,R0
STRLT R1,[R0]
ADD R0,R0,#4
CMP R0,R14
CMPLT R5,R0
STRLT R2,[R0]
ADD R0,R0,#4
CMP R0,R14
CMPLT R5,R0
STRLT R3,[R0]
ADD R0,R0,#4
CMP R4,#4
BLE loop51
LDMIA R6!,{R1-R4}
CMP R0,R14
CMPLT R5,R0
STRLT R1,[R0]
ADD R0,R0,#4
CMP R0,R14
CMPLT R5,R0
STRLT R2,[R0]
ADD R0,R0,#4
CMP R0,R14
CMPLT R5,R0
STRLT R3,[R0]
ADD R0,R0,#4
CMP R0,R14
CMPLT R5,R0
STRLT R4,[R0]
B loop51
.stmfullnextline
LDR R0,[R12,#v.hbytes]
ADD R5,R5,R0
ADD R14,R14,R0
B loop50


.err
ORR R14,R14,#1<<28
MOVS PC,R14

.badfileerr
ADR R0,badfileerrtext
B err
.badfileerrtext
DCD &809D20
DCB "FastSpr : File not found"
DCB 0
ALIGN
.badfileerr2
ADR R0,badfileerrtext2
B err
.badfileerrtext2
DCD &809D21
DCB "FastSpr : File not suitable for this module"
DCB 0
ALIGN
.nospaceerr
ADR R0,nospaceerrtext
B err
.nospaceerrtext
DCD &809D22
DCB "FastSpr : No room in RMA for file"
DCB 0
ALIGN
.nodataerr
ADR R0,nodatatext
B err
.nodatatext
DCD &809D23
DCB "FastSpr : Attempt to plot with no valid spritefile"
DCB 0
ALIGN
.toobigerr
ADR R0,toobigtext
B err
.toobigtext
DCD &809D24
DCB "FastSpr : Sprite number out of range"
DCB 0
ALIGN
.toowideerr
ADR R0,toowideerrtext
B err
.toowideerrtext
DCD &809D25
DCB "FastSpr : Clip window too wide"
DCB 0
ALIGN
.badwindow
ADR R0,badwindowtext
B err
.badwindowtext
DCD &809D26
DCB "FastSpr : Bad clipping window"
DCB 0
ALIGN
.unknownswi
ADR R0,unknownswitext
B err
.unknownswitext
DCD &809D27
DCB "FastSpr : Unknown FastSpr SWI"
DCB 0
ALIGN
