#name Code.Code
#type &ffd

#include <Bolmaster$Path>Sources.Structures
#include <Bolmaster$Path>Sources.Variables
#include <Bolmaster$Path>Sources.Macros
#include <Main$Path>Extasm.AsmLib.MYDIV
#set canvaswidth=320
#set hbytes=320
STMFD R13!,{R14}
BL setupvars
LDMVSFD R13!,{PC}
STR R13,[R12,#v.basicstack]
;OK, now you can do what you like
BL setup
BL getfiles
BVS err
BL vetlevel
BVS err
BL readback
BVS err
BL sortscreen
BL setupmaster
BL mainloop
B exit


.mainloop
STMFD R13!,{R14}
LDR R0,[R12,#v.startxpos]
LDR R1,[R12,#v.startypos]
STR R0,[R12,#v.plxpos]
STR R1,[R12,#v.plypos]
.loop
MOV R0,#1
STR R0,[R12,#v.masterplot]
BL runclocks
BL runexplomap
BL setupcanvas
BL getmotion
BL processmaster
BL movecent
BL processedge
BL processbul
BL plotplayer
BL processexplo
BL processspecial
BL colchmaster
MOV R0,#0
STR R0,[R12,#v.masterplot]
BL runclocks
BL runexplomap
BL setupcanvas
BL processmaster
BL movecent
BL plotbackdrop
BL processedge
BL processbul
BL plotplayer
BL processexplo
BL processspecial
BL colchmaster
BL updatehealth
BL writescreen
SWI OS_ReadEscapeState
BCC loop
LDMFD R13!,{PC}

.makemaster
STMFD R13!,{R14}
MOV R0,#mastertab
MOV R1,#mastertab<<24
MOV R2,#%10010010000+(3<<18)
MOV R3,#160<<12
MOV R4,#96<<12
MOV R5,#0
MOV R6,#0
MOV R7,#0
MOV R8,#&0010001E
SWI Amnesia_MakeObject
LDMFD R13!,{PC}

.runclocks
LDR R0,[R12,#v.timer]
ADD R0,R0,#1
STR R0,[R12,#v.timer]
LDR R0,[R12,#v.weptimer]
CMP R0,#0
ADD R0,R0,#1
STRGE R0,[R12,#v.weptimer]
MOV PC,R14

.getmotion
STMFD R13!,{R14}
MOV R3,#0
MOV R0,#129
MOV R1,#97 EOR &FF
MOV R2,#&FF
SWI OS_Byte
CMP R2,#&FF
EOREQ R3,R3,#1
MOV R0,#129
MOV R1,#66 EOR &FF
MOV R2,#&FF
SWI OS_Byte
CMP R2,#&FF
EOREQ R3,R3,#1<<1
MOV R0,#129
MOV R1,#79 EOR &FF
MOV R2,#&FF
SWI OS_Byte
CMP R2,#&FF
EOREQ R3,R3,#1<<2
MOV R0,#129
MOV R1,#104 EOR &FF
MOV R2,#&FF
SWI OS_Byte
CMP R2,#&FF
EOREQ R3,R3,#1<<3
MOV R0,#129
MOV R1,#73 EOR &FF
MOV R2,#&FF
SWI OS_Byte
CMP R2,#&FF
EOREQ R3,R3,#1<<4
STR R3,[R12,#v.keys1]
LDMFD R13!,{PC}

.processmaster
STMFD R13!,{R14}
ADR R0,masterremote
MOV R1,R12
SWI Amnesia_Remote
MOV R0,#mastertab
MOV R1,#0
LDR R2,[R12,#v.masterplot]
SWI Amnesia_SelectTable
MOV R5,#0
.loop1
SWI Amnesia_ProcessTable
ADD R5,R5,#1
CMP R2,#0
BNE loop1
CMP R5,#1
BEQ setupmaster
LDMFD R13!,{PC}

DCD &006E0000; this is here for a reason - see Amnesia_Remote
.masterremote
STMFD R13!,{R1-R8,R14}
STR R10,[R12,#v.plobj]
LDR R3,[R12,#v.plxpos]
LDR R4,[R12,#v.plypos]
STR R3,[R10,#8]
STR R4,[R10,#12]
LDR R5,[R10,#28]
MOV R6,R5,LSL #16
MOV R6,R6,LSR #16
MOV R5,R5,LSR #16

ADD R4,R4,R6,LSL #11
SUB R3,R3,R5,LSL #11
ADD R4,R4,#1<<12; one pixel
transnet R9,R3,R4
LDRB R2,[R9]
ADD R3,R3,R5,LSL #11
transnet R9,R3,R4
LDRB R0,[R9]
ORR R2,R2,R0
ADD R3,R3,R5,LSL #11
SUB R3,R3,#1<<12
transnet R9,R3,R4
LDRB R0,[R9]
ORR R2,R2,R0
LDR R3,[R10,#8]
LDR R4,[R10,#12]
LDR R0,[R10,#32]
ORR R1,R0,#3<<1
TST R2,#1<<7
STRNE R1,[R10,#32]
BNE masteronfloor
TST R0,#1<<1
BIC R0,R0,#1<<1
STR R0,[R10,#32]
BNE masteronfloor
TST R0,#1<<2
BIC R0,R0,#1<<2
STR R0,[R10,#32]
BNE masteronfloor

;master in empty space
LDR R1,[R12,#v.keys1]
LDR R5,[R10,#16]
LDR R6,[R10,#20]
SUB R5,R5,R5,ASR #5
ADD R6,R6,#2<<11
TST R1,#1
BEQ flynoleft
CMP R5,#0
SUB R5,R5,#1<<10
SUBGT R5,R5,#1<<10
.flynoleft
TST R1,#1<<1
BEQ flynoright
CMP R5,#0
ADD R5,R5,#1<<10
ADDLT R5,R5,#1<<10
.flynoright
.masterflyins
BL speedlim
STR R5,[R10,#16]
STR R6,[R10,#20]
LDR R0,[R10,#32]
LDR R1,[R12,#v.keys1]
TST R1,#1
BICNE R0,R0,#1
TST R1,#1<<1
ORRNE R0,R0,#1
STR R0,[R10,#32]

BL bcheck
BL speedlim
STR R5,[R10,#16]
STR R6,[R10,#20]

ADD R0,R10,#8
LDMIA R0,{R3-R6}
ADD R3,R3,R5
ADD R4,R4,R6
STR R3,[R10,#8]
STR R4,[R10,#12]
STR R3,[R12,#v.plxpos]
STR R4,[R12,#v.plypos]

LDR R1,[R12,#v.keys1]
TST R1,#1<<4
BEQ noheadwep
LDR R0,[R12,#v.weptimer]
CMP R0,#0
BGE noheadwep
MOV R0,#0
STR R0,[R12,#v.weptimer]
MOV R0,#1
STR R0,[R12,#v.weptype]
.noheadwep
LDMFD R13!,{R1-R8,PC}

.masteronfloor
LDR R1,[R12,#v.keys1]
LDR R5,[R10,#16]
LDR R6,[R10,#20]
TST R1,#3
SUBEQ R5,R5,R5,ASR #1
SUBNE R5,R5,R5,ASR #4
TST R1,#1
BEQ floornoleft
SUB R5,R5,#1<<11
CMP R5,#0
MOVGT R5,#0
.floornoleft
TST R1,#1<<1
BEQ floornoright
ADD R5,R5,#1<<11
CMP R5,#0
MOVLT R5,#0
.floornoright
TST R1,#1<<2
BEQ nojump
MOV R6,#-14<<12
TST R1,#1<<3
MOVNE R6,#-8<<12
LDR R0,[R10,#32]
BIC R0,R0,#3<<1
STR R0,[R10,#32]
.nojump
B masterflyins

.speedlim
LDR R0,[R10,#28]
MOV R1,R0,LSL #15
MOV R1,R1,LSR #16
MOV R0,R0,LSR #16
ADD R0,R0,#7
ADD R1,R1,#7
MOV R0,R0,LSL #12
MOV R1,R1,LSL #12
CMP R5,R0
MOVGT R5,R0
CMN R5,R0
RSBLT R5,R0,#0
CMP R6,R1
MOVGT R6,R1
CMN R6,R1
RSBLT R6,R1,#0
MOV PC,R14

.plotplayer
STMFD R13!,{R14}
MOV R0,#0
STR R0,[R12,#v.nutbmog]
LDR R10,[R12,#v.plobj]
LDR R9,[R10,#32]
AND R9,R9,#1
MOVS R8,R9
MOVEQ R8,#-1

LDR R1,[R12,#v.plxpos]
LDR R2,[R12,#v.plypos]
LDR R3,[R12,#v.xplotofs]
LDR R4,[R12,#v.yplotofs]
ADD R1,R1,R3
ADD R2,R2,R4
MOV R5,R1,ASR #12
MOV R6,R2,ASR #12
SUB R6,R6,#1
LDR R4,[R12,#v.weptimer]
CMP R4,#0
BGE wepactive
.wepactiveins
LDR R0,[R12,#v.masterplot]
CMP R0,#0
BNE plotplayerskip
ADD R0,R9,#mastertab<<24
MOV R1,R5
MOV R2,R6
SWI FastSpr_Plot
LDR R0,[R10,#8]
MOV R0,R0,LSR #16
AND R0,R0,#3
CMP R0,#3
MOVEQ R0,#1
CMP R0,#0
SUBEQ R1,R1,R8
CMP R0,#2
;ADDEQ R1,R1,R8
CMP R0,#1
SUBNE R2,R2,#1
MOV R0,R0,LSL #16
ADD R0,R0,#(mastertab<<24)+2
ADD R0,R0,R9
SWI FastSpr_Plot
.plotplayerskip
LDMFD R13!,{PC}

.nutsprtab
DCD &010000
DCD &010000
DCD &020000
DCD &020000
DCD &020000
DCD &020000
DCD &010000
DCD &000000
DCD &030000
DCD &040000
DCD &040000
DCD &040000
DCD &040000
DCD &040000
DCD &040000
DCD &030000

.nutarmtab
DCB 1,1,0,0,0,0,1,2,3,4,5,5,5,5,4,3
.nutarmspr
DCB 0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,0

.wepactive
MOV R4,R4,LSR #1
CMP R4,#16
BGE wepactivend
ADR R1,nutsprtab
LDR R0,[R1,R4,LSL #2]
ADD R0,R0,R9
ADD R0,R0,#mastertab<<24
MOV R1,R5
MOV R2,R6
SWI FastSpr_Plot
ADR R3,nutarmtab
LDRB R0,[R3,R4]
SUB R0,R0,#2
CMP R8,#1
ADDEQ R1,R5,R0
SUBNE R1,R5,R0
ADR R3,nutarmspr
LDRB R0,[R3,R4]

CMP R0,#1
SUBNE R2,R2,#1
MOV R0,R0,LSL #16
ADD R0,R0,#(mastertab<<24)+2
ADD R0,R0,R9
SWI FastSpr_Plot
LDR R4,[R12,#v.weptimer]
CMP R4,#20
BLEQ nutimpact
LDMFD R13!,{PC}

.nutimpact
STMFD R13!,{R14}
LDR R3,[R10,#8]
LDR R4,[R10,#12]
ADD R3,R3,R8,ASL #15
ADD R3,R3,R8,ASL #14
SUB R4,R4,#8<<12
BL dodamage
LDMFD R13!,{PC}

.wepactivend
MOV R0,#-1
STR R0,[R12,#v.weptimer]
B wepactiveins


.makeexplo
; Make an explosion object
STMFD R13!,{R0-R7,R14}

LDR R0,[R12,#v.rnseed]
ADD R0,R0,#13
EOR R0,R0,R0,ROR #9
MOV R7,R0
ADD R0,R0,#13
EOR R0,R0,R0,ROR #9
MOV R5,R0
ADD R0,R0,#13
EOR R0,R0,R0,ROR #9
MOV R6,R0
ADD R0,R0,#13
EOR R0,R0,R0,ROR #9

STR R0,[R12,#v.rnseed]
AND R1,R0,#3
CMP R1,#3
MOVEQ R1,#2
MOV R0,#explotab

ADD R1,R1,#explotab<<24
MOV R2,#%1000110101
ANDS R5,R5,#3
ADDEQ R3,R3,#4<<12
CMP R5,#2
SUBEQ R3,R3,#4<<12
AND R6,R6,#7<<12
ADD R4,R4,R6
SUB R4,R4,#7<<11
MOV R5,#0
MOV R6,#0
AND R7,R7,#&7F
ADD R7,R7,#&06000020
SWI Amnesia_MakeObject
LDMFD R13!,{R0-R7,PC}

.processexplo
;process the explosion table
STMFD R13!,{R14}
MOV R0,#0
MOV R1,R12
SWI Amnesia_Remote
MOV R0,#explotab
MOV R1,#0
LDR R2,[R12,#v.masterplot]
SWI Amnesia_SelectTable

.loopb
SWI Amnesia_ProcessTable
CMP R2,#0
BNE loopb
LDMFD R13!,{PC}

.processspecial
LDR PC,[R12,#v.specialadr]
.runexplomap
;Produce the large explosions seen in the game.  It lets one explosion
;set off any of it's nearest neighbours.  The currently active
;explosions are stored in a list called the explomap.  Explosions
;are 'active' for the first frame after their creation
;explomap entries are offsets from the levelnet, not addresses

STMFD R13!,{R14}
LDR R0,[R12,#v.timer]
TST R0,#&1
LDMNEFD R13!,{PC}
LDR R0,[R12,#v.explomap]
STR R0,[R12,#v.explomap]
CMP R0,#0
LDR R11,[R12,#v.levelnet]
LDREQ R10,[R12,#v.explomap1]
LDRNE R10,[R12,#v.explomap2]
MOV R9,#explomaplen
LDR R7,[R12,#v.netxsize]
LDR R8,[R12,#v.netysize]
MOV R7,R7,LSL #2
MOV R8,R8,LSL #2
.loope
#rept 8
LDR R6,[R10],#4
CMP R6,#0
BLNE domap
#endr
SUBS R9,R9,#8
BGT loope
LDMFD R13!,{PC}

.domap
STMFD R13!,{R14}
MOV R0,#0
STR R0,[R10,#-4]
;test for data area erase
AND R0,R6,#3
CMP R0,#1
CMPNE R0,#2
BNE nomaperase
LDR R2,[R12,#v.levelshift]
ADD R2,R2,#netshift
MOV R0,R6,LSR R2
AND R0,R0,#3
CMP R0,#1
CMPNE R0,#2
BNE nomaperase
ADD R2,R2,#2
MOV R1,R6,LSR R2

SUB R2,R2,#netshift+2
MOV R1,R1,LSL R2
SUB R0,R7,#1
AND R2,R6,R0
ADD R1,R1,R2,LSR #2
MOV R0,#0
LDR R2,[R12,#v.leveldata]
STRB R0,[R2,R1]

.nomaperase

;test left
SUB R5,R7,#1
TST R6,R5
SUB R0,R6,#1
BLNE domaptest

;test right
SUB R5,R7,#1
ADD R0,R6,#1
TST R6,R5
BLNE domaptest

;test up
SUBS R0,R6,R7
BLGE domaptest

ADD R0,R6,R7
MUL R1,R7,R8
CMP R0,R1
BLLT domaptest
MOV R0,#0
STRB R0,[R11,R6];wipe the current object fron the micronet
LDMFD R13!,{PC} 

.domaptest
LDRB R2,[R11,R6]
LDRB R1,[R11,R0]
TST R1,#1       ;have we blown this one up already
MOVNE PC,R14
TST R2,#&20     ;if this block is an E explosion
TSTNE R1,#&30   ;and the adjacent block is any explosive
BNE maptesttrue ;blow it up
TST R2,#&10     ;if this block is an H explosion
TSTNE R1,#&10   ;and the adjacent block is an H explosive
BNE maptesttrue ;blow it up
MOV PC,R14

.maptesttrue
STMFD R13!,{R14}
ADD R0,R11,R0
BL addexplomap
LDMFD R13!,{PC}

.addexplomap
;add an entry to the explomap
STMFD R13!,{R0-R4,R14}
MOV R4,R0
LDRB R1,[R0]
ORR R1,R1,#1
STRB R1,[R0]

LDR R2,[R12,#v.levelnet]
SUB R0,R0,R2
LDR R2,[R12,#v.explomap]
RSB R2,R2,#1
CMP R2,#0
LDREQ R2,[R12,#v.explomap2]
LDRNE R2,[R12,#v.explomap1]
LDR R3,[R12,#v.exploptr]
STR R0,[R2,R3]
ADD R3,R3,#12;a bit of interleaving
CMP R3,#explomaplen*4
SUBGE R3,R3,#explomaplen*4
STR R3,[R12,#v.exploptr]
backtransnet R4
MOV R3,R0
MOV R4,R1
BL makeexplo
LDMFD R13!,{R0-R4,PC}

.dodamage
;'damage' a block - normally causes it to explode
STMFD R13!,{R5-R6,R14}
LDR R5,[R12,#v.netxsize]
LDR R6,[R12,#v.netysize]
CMP R3,R5,LSL #5+12
BGE dodamoff
CMP R4,R6,LSL #5+12
BGE dodamoff
CMP R3,#0
BLT dodamoff
CMP R4,#0
BLT dodamoff
transnet R0,R3,R4
LDRB R5,[R0]
TST R5,#&10 ;the high explosive bit
BEQ damnotexplo
STMFD R13!,{R3-R5}
BL addexplomap
LDMFD R13!,{R3-R5}
.damnotexplo
TST R5,#&0C
BLNE writenutbmog

.dodamoff
LDMFD R13!,{R5-R6,PC}

.writenutbmog
STMFD R13!,{R14}
transdata R0,R3,R4
STR R0,[R12,#v.nutbmog]
LDMFD R13!,{PC}

.movecent
;move Amnesia's plot offset to keep the master in the centre of the
;screen.  The 'plotnibble' is to do with the shifting of the screen
;to the left when it is written from the canvas to the screen.
STMFD R13!,{R14}
LDR R0,[R12,#v.plxpos]
MOV R0,R0,ASR #12
SUB R0,R0,#160
STR R0,[R12,#v.xofs]
LDR R1,[R12,#v.plypos]
MOV R1,R1,ASR #12
SUB R1,R1,#96
STR R1,[R12,#v.yofs]
LDR R2,[R12,#v.xofs]
AND R2,R2,#3
STR R2,[R12,#v.plotnibble]

RSB R0,R0,#0
RSB R1,R1,#0
ADD R0,R0,R2
MOV R0,R0,ASL #12
MOV R1,R1,ASL #12
STR R0,[R12,#v.xplotofs]
STR R1,[R12,#v.yplotofs]
SWI Amnesia_SetPlotOffset

LDMFD R13!,{PC}

.processedge
;process the edge table.  This plots the 3D bits to the platforms and 
;any other part of the backdrop that needs plotting as a sprite.
STMFD R13!,{R14}
MOV R0,#0
SWI Amnesia_Remote
MOV R0,#backtab
MOV R1,#0
LDR R2,[R12,#v.masterplot]
SWI Amnesia_SelectTable
.loopa
SWI Amnesia_ProcessTable
CMP R2,#0
BNE loopa
LDMFD R13!,{PC}


.processbul
;process the dalek's bullets
STMFD R13!,{R14}
ADR R0,bulremote
MOV R1,R12
SWI Amnesia_Remote
MOV R0,#bultab
MOV R1,#0
LDR R2,[R12,#v.masterplot]
SWI Amnesia_SelectTable
.loopg
SWI Amnesia_ProcessTable
CMP R2,#0
BNE loopg
LDMFD R13!,{PC}

DCD &006E0000; this is here for a reason - see Amnesia_Remote
.bulremote
STMFD R13!,{R1-R8,R14}
transnet R9,R3,R4
LDRB R2,[R9]
TST R2,#1<<6
MOVNE R0,#0
STRNE R0,[R10];delete object
LDMFD R13!,{R1-R8,PC}


.colchmaster
;check if the player has been hit by any bullets
STMFD R13!,{R14}
MOV R0,#mastertab
MOV R1,#bultab
.loopi
SWI Amnesia_CollisionCheck
CMP R0,#0
BEQ colchmasterend
LDR R4,[R12,#v.health]
SUB R4,R4,#1
STR R4,[R12,#v.health]
CMP R4,#0
MOV R4,#0
STRLT R4,[R0]
STR R4,[R1]
B loopi
.colchmasterend
LDMFD R13!,{PC}

.updatehealth
STMFD R13!,{R14}
LDR R0,[R12,#v.health]
LDR R1,[R12,#v.lasthealth]
CMP R0,R1
LDMEQFD R13!,{PC}
BL setupscreen
LDR R3,[R12,#v.health]
CMP R3,#8
MOVGT R3,#8
MOV R1,#48
MOV R2,#224
MOV R4,#8
.loopj
CMP R3,#0
MOV R0,#(generaltab<<24)+1
MOVLE R0,#(generaltab<<24)
SWI FastSpr_Plot
ADD R1,R1,#32
SUB R3,R3,#1
SUBS R4,R4,#1
BGT loopj
LDR R0,[R12,#v.health]
STR R0,[R12,#v.lasthealth]
BL setupcanvas
LDMFD R13!,{PC}



.writescreen
;an optimised routine to write out the canvas to the screen with a shift
;left of 0,1,2 or 3 pixels.
;
;Here, incidentally, is where you can add support for mode 49.

STMFD R13!,{R14}
MOV R0,#1
SWI Blitz_Wait
LDR R10,[R12,#v.screenadr]
ADD R10,R10,#320*8
ADD R10,R10,#4
LDR R11,[R12,#v.canvas]
MOV R9,#192
LDR R2,[R12,#v.gminx]
AND R2,R2,#3
ADR R1,shifttab
LDR R0,[R1,R2,LSL #2]
ADD R0,R0,R1
MOV PC,R0

.shifttab
DCD shift0-shifttab
DCD shift1-shifttab
DCD shift2-shifttab
DCD shift3-shifttab

.shift0
.sloopc
STMFD R13!,{R10-R11}
#rept 9
LDMIA R11!,{R0-R7}
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
STMIA R10!,{R0-R7}
#endr
LDMIA R11!,{R0-R5}
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
MOV R0,R0
STMIA R10!,{R0-R5}
LDMFD R13!,{R10-R11}
ADD R10,R10,#canvaswidth
ADD R11,R11,#hbytes
SUBS R9,R9,#1
BGT sloopc
LDMFD R13!,{PC}

.shift1
.sloopb
STMFD R13!,{R10-R11}

#rept 9
LDMIA R11!,{R0-R8}
SUB R11,R11,#4
MOV R0,R0,LSR #8
ORR R0,R0,R1,LSL #24
MOV R1,R1,LSR #8
ORR R1,R1,R2,LSL #24
MOV R2,R2,LSR #8
ORR R2,R2,R3,LSL #24
MOV R3,R3,LSR #8
ORR R3,R3,R4,LSL #24
MOV R4,R4,LSR #8
ORR R4,R4,R5,LSL #24
MOV R5,R5,LSR #8
ORR R5,R5,R6,LSL #24
MOV R6,R6,LSR #8
ORR R6,R6,R7,LSL #24
MOV R7,R7,LSR #8
ORR R7,R7,R8,LSL #24
STMIA R10!,{R0-R7}
#endr
LDMIA R11!,{R0-R6}
SUB R11,R11,#4
MOV R0,R0,LSR #8
ORR R0,R0,R1,LSL #24
MOV R1,R1,LSR #8
ORR R1,R1,R2,LSL #24
MOV R2,R2,LSR #8
ORR R2,R2,R3,LSL #24
MOV R3,R3,LSR #8
ORR R3,R3,R4,LSL #24
MOV R4,R4,LSR #8
ORR R4,R4,R5,LSL #24
MOV R5,R5,LSR #8
ORR R5,R5,R6,LSL #24
STMIA R10!,{R0-R5}

LDMFD R13!,{R10-R11}
ADD R10,R10,#canvaswidth
ADD R11,R11,#hbytes
SUBS R9,R9,#1
BGT sloopb
LDMFD R13!,{PC}

.shift2
.sloopd
STMFD R13!,{R10-R11}

#rept 9
LDMIA R11!,{R0-R8}
SUB R11,R11,#4
MOV R0,R0,LSR #16
ORR R0,R0,R1,LSL #16
MOV R1,R1,LSR #16
ORR R1,R1,R2,LSL #16
MOV R2,R2,LSR #16
ORR R2,R2,R3,LSL #16
MOV R3,R3,LSR #16
ORR R3,R3,R4,LSL #16
MOV R4,R4,LSR #16
ORR R4,R4,R5,LSL #16
MOV R5,R5,LSR #16
ORR R5,R5,R6,LSL #16
MOV R6,R6,LSR #16
ORR R6,R6,R7,LSL #16
MOV R7,R7,LSR #16
ORR R7,R7,R8,LSL #16
STMIA R10!,{R0-R7}
#endr
LDMIA R11!,{R0-R6}
SUB R11,R11,#4
MOV R0,R0,LSR #16
ORR R0,R0,R1,LSL #16
MOV R1,R1,LSR #16
ORR R1,R1,R2,LSL #16
MOV R2,R2,LSR #16
ORR R2,R2,R3,LSL #16
MOV R3,R3,LSR #16
ORR R3,R3,R4,LSL #16
MOV R4,R4,LSR #16
ORR R4,R4,R5,LSL #16
MOV R5,R5,LSR #16
ORR R5,R5,R6,LSL #16
STMIA R10!,{R0-R5}

LDMFD R13!,{R10-R11}
ADD R10,R10,#canvaswidth
ADD R11,R11,#hbytes
SUBS R9,R9,#1
BGT sloopd
LDMFD R13!,{PC}

.shift3
.sloope
STMFD R13!,{R10-R11}

#rept 9
LDMIA R11!,{R0-R8}
SUB R11,R11,#4
MOV R0,R0,LSR #24
ORR R0,R0,R1,LSL #8
MOV R1,R1,LSR #24
ORR R1,R1,R2,LSL #8
MOV R2,R2,LSR #24
ORR R2,R2,R3,LSL #8
MOV R3,R3,LSR #24
ORR R3,R3,R4,LSL #8
MOV R4,R4,LSR #24
ORR R4,R4,R5,LSL #8
MOV R5,R5,LSR #24
ORR R5,R5,R6,LSL #8
MOV R6,R6,LSR #24
ORR R6,R6,R7,LSL #8
MOV R7,R7,LSR #24
ORR R7,R7,R8,LSL #8
STMIA R10!,{R0-R7}
#endr
LDMIA R11!,{R0-R6}
SUB R11,R11,#4
MOV R0,R0,LSR #24
ORR R0,R0,R1,LSL #8
MOV R1,R1,LSR #24
ORR R1,R1,R2,LSL #8
MOV R2,R2,LSR #24
ORR R2,R2,R3,LSL #8
MOV R3,R3,LSR #24
ORR R3,R3,R4,LSL #8
MOV R4,R4,LSR #24
ORR R4,R4,R5,LSL #8
MOV R5,R5,LSR #24
ORR R5,R5,R6,LSL #8
STMIA R10!,{R0-R5}

LDMFD R13!,{R10-R11}
ADD R10,R10,#canvaswidth
ADD R11,R11,#hbytes
SUBS R9,R9,#1
BGT sloope
LDMFD R13!,{PC}

.wipecanvas
;This is for testing - it doesn't get called anymore
STMFD R13!,{R14}
LDR R11,[R12,#v.canvas]
MOV R0,#&40404040
MOV R1,R0
MOV R2,R0
MOV R3,R0
MOV R4,R0
MOV R5,R0
MOV R6,R0
MOV R7,R0
MOV R9,#240
.loop3
#rept 10
STMIA R11!,{R0-R7}
#endr
SUBS R9,R9,#1
BGT loop3
LDMFD R13!,{PC}

.plotbackdrop
;overwrites the canvas with the backdrop pattern and the bits of the
;foreground which have transparency.  It's a bit of black magic,
;this...
;A lot more is plotted on top of this backdrop by the sprite plotter
;as part of the ProcessTables
STMFD R13!,{R14}
MOV R0,#backtab
SWI Amnesia_WipeTable
MOV R0,#backtab
SWI Amnesia_GetTableAddress
ADD R0,R0,#16
STR R0,[R12,#v.backtablim]
ADD R0,R0,#32*backtablen
SUB R0,R0,#backtablen
STR R0,[R12,#v.backtabptr]

LDR R3,[R12,#v.xofs]
LDR R4,[R12,#v.yofs]
STR R3,[R12,#v.gminx]
STR R4,[R12,#v.gminy]
ADD R0,R3,#320
STR R0,[R12,#v.gmaxx]
ADD R0,R4,#192
STR R0,[R12,#v.gmaxy]
LDR R0,[R12,#v.gminy]
STR R0,[R12,#v.gy]
BL updatescrollinc
BL makehell
LDR R10,[R12,#v.canvas]
.plotbackloop
BL backreload

.writeline
;outputs one line of graphics to the canvas
LDR R8,[R12,#v.gy]
LDR R1,[R12,#v.gmaxy]
SUB R1,R1,R8
CMP R1,#32
MOVGT R1,#32
STR R1,[R12,#v.gbreak]
AND R8,R8,#31
LDR R2,[R12,#v.gminx]
AND R2,R2,#&1C
ADR R1,lwtab
LDR R0,[R1,R2]
ADD R0,R0,R1
MOV PC,R0
.lwtab
DCD lwloop0-lwtab
DCD lwloop1-lwtab
DCD lwloop2-lwtab
DCD lwloop3-lwtab
DCD lwloop4-lwtab
DCD lwloop5-lwtab
DCD lwloop6-lwtab
DCD lwloop7-lwtab

;each of these routines writes a line fron the sprite file levpix to the
;canvas.  lwloop0 is a straight plot, lwloop1 shifts the graphics left 4
;pixels, lwloop2 by 8 pixels, etc.  Then .writescreen will take care of
;the final 0,1,2 or 3 pixel shift to get the horizontal position right.

.lwloop0
ADD R9,R12,#v.backbuf
#rept 10
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R7}
STMIA R10!,{R0-R7}
#endr
ADD R8,R8,#1
LDR R1,[R12,#v.gbreak]
CMP R8,R1
BLT lwloop0
B lwins

.lwloop1
ADD R9,R12,#v.backbuf
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
ADD R11,R11,#4
LDMIA R11,{R1-R7}
STMIA R10!,{R1-R7}
#rept 9
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R7}
STMIA R10!,{R0-R7}
#endr
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0}
STMIA R10!,{R0}
ADD R8,R8,#1
LDR R1,[R12,#v.gbreak]
CMP R8,R1
BLT lwloop1
B lwins
.lwloop2
ADD R9,R12,#v.backbuf
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
ADD R11,R11,#8
LDMIA R11,{R2-R7}
STMIA R10!,{R2-R7}
#rept 9
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R7}
STMIA R10!,{R0-R7}
#endr
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R1}
STMIA R10!,{R0-R1}
ADD R8,R8,#1
LDR R1,[R12,#v.gbreak]
CMP R8,R1
BLT lwloop2
B lwins
.lwloop3
ADD R9,R12,#v.backbuf
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
ADD R11,R11,#12
LDMIA R11,{R3-R7}
STMIA R10!,{R3-R7}
#rept 9
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R7}
STMIA R10!,{R0-R7}
#endr
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R2}
STMIA R10!,{R0-R2}
ADD R8,R8,#1
LDR R1,[R12,#v.gbreak]
CMP R8,R1
BLT lwloop3
B lwins
.lwloop4
ADD R9,R12,#v.backbuf
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
ADD R11,R11,#16
LDMIA R11,{R4-R7}
STMIA R10!,{R4-R7}
#rept 9
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R7}
STMIA R10!,{R0-R7}
#endr
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R3}
STMIA R10!,{R0-R3}
ADD R8,R8,#1
LDR R1,[R12,#v.gbreak]
CMP R8,R1
BLT lwloop4
B lwins
.lwloop5
ADD R9,R12,#v.backbuf
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
ADD R11,R11,#20
LDMIA R11,{R5-R7}
STMIA R10!,{R5-R7}
#rept 9
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R7}
STMIA R10!,{R0-R7}
#endr
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R4}
STMIA R10!,{R0-R4}
ADD R8,R8,#1
LDR R1,[R12,#v.gbreak]
CMP R8,R1
BLT lwloop5
B lwins
.lwloop6
ADD R9,R12,#v.backbuf
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
ADD R11,R11,#24
LDMIA R11,{R6-R7}
STMIA R10!,{R6-R7}
#rept 9
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R7}
STMIA R10!,{R0-R7}
#endr
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R5}
STMIA R10!,{R0-R5}
ADD R8,R8,#1
LDR R1,[R12,#v.gbreak]
CMP R8,R1
BLT lwloop6
B lwins
.lwloop7
ADD R9,R12,#v.backbuf
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
ADD R11,R11,#28
LDMIA R11,{R7}
STMIA R10!,{R7}
#rept 9
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R7}
STMIA R10!,{R0-R7}
#endr
LDR R11,[R9],#4
ADD R11,R11,R8,LSL #5
LDMIA R11,{R0-R6}
STMIA R10!,{R0-R6}
ADD R8,R8,#1
LDR R1,[R12,#v.gbreak]
CMP R8,R1
BLT lwloop7
B lwins
.lwins
LDR R8,[R12,#v.gy]
ADD R8,R8,#32
BIC R8,R8,#31
STR R8,[R12,#v.gy]
LDR R0,[R12,#v.gmaxy]
CMP R8,R0
BLT plotbackloop


LDMFD R13!,{PC}



.backreload
;get the next line of blocks from the leveldata, so we know what to
;plot where.  We scan from right to left.
STMFD R13!,{R8-R11,R14}
LDR R5,[R12,#v.netxsize]
LDR R6,[R12,#v.netysize]
LDR R3,[R12,#v.gmaxx]
LDR R7,[R12,#v.gminx]
LDR R4,[R12,#v.gy]
MOV R3,R3,ASR #5
MOV R4,R4,ASR #5
MOV R7,R7,ASR #5
ADD R9,R12,#v.backbuf
SUB R9,R9,#4
ADD R11,R12,#v.backtab
MOV R8,#12
ADD R9,R9,R8,LSL #2
.loop5
CMP R3,#0
BLT backreloff
CMP R4,#0
BLT backreloff
CMP R3,R5
BGE backreloff
CMP R4,R6
BGE backreloff

LDR R10,[R12,#v.leveldata]
CMP R10,#0
BEQ backreloff
MUL R2,R4,R5
ADD R10,R10,R3
ADD R10,R10,R2

LDRB R0,[R10]
B backrelins
.backreloff
MOV R0,#128
.backrelins
AND R0,R0,#&FF
LDR R2,[R12,#v.bmogtabadr]
LDR R1,[R2,R0,LSL #2]
CMP R1,#0
BEQ nobmogentry
ADD R1,R1,R2
LDR R0,[R1,#bmog.pix]

LDR R2,[R1,#bmog.objflags]
CMP R2,#0
BLNE bmoggen
.nobmogentry
CMP R0,#0
BNE backnotrans
ADD R0,R3,#24
rem3 R0
ADD R1,R4,#24
rem3 R1
CMP R0,#3
CMPLT R1,#4
MOVGE PC,#0
ADD R0,R0,R0,LSL #1
ADD R0,R0,R1

.backnotrans
LDR R1,[R11,R0,LSL #2]
STR R1,[R9,#-4]!
SUBS R8,R8,#1
BLE backrelerr
SUB R3,R3,#1
CMP R3,R7
BGE loop5
LDMFD R13!,{R8-R11,PC}

.bmoggen
; the object generator.  Makes all of the objects associated with the
; backdrop.  Uses the BMOG table.
;bits:
;1<<31 - plot always
;1<<30 - use the timer
;1<<29 }-perimeter check to left,right,up or down (0,1,2, or 3<<28)
;1<<28 }
;1<<27 - don't make if greater than
;1<<26 - don't make if less than
;1<<25 - don't make if not equal
;1<<24 - don't make if equal to objdata
;1<<23 - make object if nutted type 2
;1<<22 - make object if nutted type 1

STMFD R13!,{R0-R11,R14}
ADD R11,R1,#bmog.objflags
.bmoggenloop
LDR R8,[R11]
LDR R9,[R11,#4]
TST R8,#1<<30
BNE bmogtimed
.bmogtimedins
TST R8,#1<<31
BNE dobmoggen
TST R8,#&F<<24
BEQ bmognoperim
;If you think about it, the 3D bits of the platforms may or may not need
;to be plotted, depending on what's around them.  This routine checks
;the perimeter against the flag entry in the BMOG table.
BL bmoggetperim
AND R0,R8,#3<<28
MOV R1,#0
CMP R0,#0
LDREQ R1,[R12,#v.bleft]
CMP R0,#1<<28
LDREQ R1,[R12,#v.bright]
CMP R0,#2<<28
LDREQ R1,[R12,#v.bup]
CMP R0,#3<<28
LDREQ R1,[R12,#v.bdown]
CMP R1,#0
BEQ bmognoperim
LDRB R2,[R1]
TST R8,#1<<24
BLNE bmognotifequal
TST R8,#1<<25
BLNE bmogifequal
TST R8,#1<<26
BLNE bmognotiflt
TST R8,#1<<27
BLNE bmognotifgt
B bmognoperim
.bmognotifequal
CMP R2,R9
BEQ bmoggenend
MOV PC,R14
.bmogifequal
CMP R2,R9
BNE bmoggenend
MOV PC,R14
.bmognotiflt
CMP R2,R9
BLT bmoggenend
MOV PC,R14
.bmognotifgt
CMP R2,R9
BGT bmoggenend
MOV PC,R14

.bmogtimed
LDR R0,[R12,#v.timer]
TST R0,R9
BEQ bmogtimedins
B bmoggenend

.bmognoperim
TST R8,#3<<22
BEQ bmognonut
LDR R0,[R12,#v.nutbmog]
CMP R0,R10
BNE bmoggenend
.bmognonut

.dobmoggen
backtransdata R10
MOV R8,R0
MOV R9,R1

ADD R11,R11,#8
LDMIA R11,{R0-R7}
SUB R11,R11,#8
ADD R3,R3,R8
ADD R4,R4,R9
;CMP R3,#&900<<12
;MOVGT PC,#0
;CMP R4,#&900<<12
;MOVGT PC,#0
;CMP R3,#0
;MOVLT PC,#0
;CMP R4,#0
;MOVLT PC,#0

CMP R0,#backtab
BNE bmogrealmake
;this bit fakes a MakeObject in a faster way
LDR R8,[R12,#v.backtabptr]
LDR R9,[R12,#v.backtablim]
SUB R8,R8,#32
CMP R8,R9
BLT bmogfull
STMIA R8,{R1-R7}
STR R8,[R12,#v.backtabptr]
.bmogfull
.bmoggenend
ADD R11,R11,#sizeof_bmog
LDR R0,[R11]
CMP R0,#0
BNE bmoggenloop
.bmoggenexit
LDMFD R13!,{R0-R11,PC}
.bmogrealmake
STMFD R13!,{R0}
SWI Amnesia_MakeObject
LDMFD R13!,{R0}
CMP R0,#specialtab
BNE bmoggenend
CMP R1,#0
BEQ bmoggenend
LDR R0,[R11,#32+8]
STR R0,[R1,#32]
B bmoggenend

.bmoggetperim
STMFD R13!,{R5-R6,R14}
LDR R5,[R12,#v.netxsize]
LDR R6,[R12,#v.netysize]
CMP R3,#0
MOVLE R0,#0
SUBGT R0,R10,#1
STR R0,[R12,#v.bleft]

CMP R3,R5
MOVGE R0,#0
ADDLT R0,R10,#1
STR R0,[R12,#v.bright]

CMP R4,#0
MOVLE R0,#0
SUBGT R0,R10,R5
STR R0,[R12,#v.bup]

CMP R4,R6
MOVGE R0,#0
ADDLT R0,R10,R5
STR R0,[R12,#v.bdown]
LDMFD R13!,{R5-R6,PC}




.makehell
;'hell' is the backdrop behind the platforms.  This routine sets up
;blocks with the right amount of shifting so that the parallax works.
STMFD R13!,{R14}
ADD R11,R12,#v.backpixtab
LDR R11,[R11]
ADD R0,R11,#96*96
STR R0,[R12,#v.hellend]
LDR R0,[R12,#v.vscrollinc]
MOV R1,#96
MUL R0,R1,R0
ADD R11,R11,R0

LDR R10,[R12,#v.hellcache]
MOV R8,#96
.loopd
LDR R9,[R12,#v.hscrollinc]
AND R0,R9,#3
BIC R9,R9,#3
ADR R1,hellshift
LDR R0,[R1,R0,LSL #2]
ADD R1,R1,R0
STMFD R13!,{R8-R11}
ADD R10,R12,#v.linecache
MOV R14,PC
MOV PC,R1
LDMFD R13!,{R8-R11}

ADD R9,R12,#v.linecache
LDMIA R9!,{R0-R7}
STMIA R10,{R0-R7}
ADD R10,R10,#32*96
LDMIA R9!,{R0-R7}
STMIA R10,{R0-R7}
ADD R10,R10,#32*96
LDMIA R9!,{R0-R7}
STMIA R10,{R0-R7}
SUB R10,R10,#64*96
ADD R10,R10,#32
ADD R11,R11,#96
LDR R0,[R12,#v.hellend]
CMP R11,R0
SUBGE R11,R11,#96*96
SUBS R8,R8,#1
BGT loopd
LDMFD R13!,{PC}

.updatescrollinc
;updates the scrollincs to make the parallax look effective.  You can get
;some strange effects if you mess about with this!
STMFD R13!,{R14}
MOV R3,#0
LDR R1,[R12,#v.xofs]
CMP R1,#0
RSBLT R1,R1,#0
MOVLT R3,#1
SUB R1,R1,R1,ASR #1
DIV96 R0,R1
MOV R2,#96
CMP R3,#1
RSBNE R1,R1,#95
STR R1,[R12,#v.hscrollinc]
MOV R3,#0
LDR R1,[R12,#v.yofs]
CMP R1,#0
RSBLT R1,R1,#0
MOVLT R3,#1
SUB R1,R1,R1,ASR #1
DIV96 R0,R1
MOV R2,#96
CMP R3,#1
RSBNE R1,R1,#95
STR R1,[R12,#v.vscrollinc]
LDMFD R13!,{PC}

.vetlevel
;checks that a level is OK and sets up values such as its size.  The level
;file at [R12,#v.leveladr] is a 256 colour sprite.  the variable leveldata
;is set to point to the sprite data.

STMFD R13!,{R14}
LDR R11,[R12,#v.leveladr]
CMP R11,#0
BEQ vetlevelerr
SUB R11,R11,#4
LDR R1,[R11,#8]
CMP R1,#128
BGT vetlevelerr
CMP R1,#0
BLT vetlevelerr
ADD R11,R11,R1;indirect to first sprite
LDR R0,[R11,#16];level width in words -1
ADD R0,R0,#1
MOV R0,R0,LSL #2
STR R0,[R12,#v.netxsize]
LDR R0,[R11,#20];level height -1
ADD R0,R0,#1
STR R0,[R12,#v.netysize]
LDR R0,[R11,#32];indirect to sprite data
ADD R11,R11,R0
STR R11,[R12,#v.leveldata]

ADD R0,R12,#v.levelnet
BL checkdiscard
LDR R0,[R12,#v.netxsize]
LDR R1,[R12,#v.netysize]
MUL R1,R0,R1
MOV R1,R1,LSL #4;multiply by 16
ADD R0,R12,#v.levelnet
ADR R2,levelnetname
MOV R3,#0
SWI Amnesia_ClaimBlock
BL buildlevelnet

LDR R0,[R12,#v.netxsize]
MOV R1,#0
CMP R0,#16
MOVEQ R1,#4
CMP R0,#32
MOVEQ R1,#5
CMP R0,#64
MOVEQ R1,#6
CMP R0,#128
MOVEQ R1,#7
CMP R0,#256
MOVEQ R1,#8
CMP R1,#0
BEQ netwidtherr
STR R1,[R12,#v.levelshift]
LDR R7,[R12,#v.levelshift]
LDR R8,[R12,#v.netysize]
LDR R9,[R12,#v.netysize]
LDR R10,[R12,#v.leveldata]
MOV R6,#0
.loop10
MOV R5,#0
.loop11
ADD R4,R5,R6,LSL R7
ADD R4,R4,R10
LDRB R0,[R4]
CMP R0,#255
BLEQ foundstart
ADD R5,R5,#1
CMP R5,R8
BLT loop11
ADD R6,R6,#1
CMP R6,R9
BLT loop10
LDMFD R13!,{PC}

.foundstart
;the player start position is marked by colour 255 in the level sprite
STMFD R13!,{R5-R10,R14}
MOV R0,#0
STRB R0,[R4]
backtransdata R4
STR R0,[R12,#v.startxpos]
STR R1,[R12,#v.startypos]
LDMFD R13!,{R5-R10,PC}


.levelnetname
DCB "LevelNet",0
ALIGN

.buildlevelnet
;The level data is stored in 2 bits.  The bit at leveldata is the sprite
;as loaded, and contains the graphics data.  Let's say for example it's
;32x32.  The 'levelnet' is built from this sprite by looking at the
;micronets in the BMOG table, and is 4 times as dense (128x128 in the
;example case).  The levelnet is used for collision checking and to
;work the explosions.

STMFD R13!,{R14}
MOV R9,#0;y coord

.loop9
LDR R0,[R12,#v.netysize]
CMP R9,R0
BGE done9
MOV R8,#0;x coord in net data
.loop8
LDR R0,[R12,#v.netxsize]
CMP R8,R0
BGE done8
LDR R11,[R12,#v.leveldata]
ADD R11,R11,R8;move x
LDR R0,[R12,#v.netxsize]
MUL R0,R9,R0
ADD R11,R11,R0;move y

LDR R10,[R12,#v.levelnet]
ADD R10,R10,R8,LSL #2
LDR R0,[R12,#v.netxsize]
MUL R0,R9,R0
ADD R10,R10,R0,LSL #4

;R11 points to leveldata point
;R10 points to levelnet point

LDRB R4,[R11]
LDR R5,[R12,#v.bmogtabadr]
LDR R6,[R5,R4,LSL #2];get bmogtable entry
MOV R0,#1
MOV R1,#2
MOV R2,#3
MOV R3,#4

CMP R6,#0
ADDNE R5,R5,R6;get entry address
LDRNE R0,[R5,#bmog.micronet0]
LDRNE R1,[R5,#bmog.micronet1]
LDRNE R2,[R5,#bmog.micronet2]
LDRNE R3,[R5,#bmog.micronet3]

LDR R6,[R12,#v.netxsize]
STR R0,[R10],R6,LSL #netshift
STR R1,[R10],R6,LSL #netshift
STR R2,[R10],R6,LSL #netshift
STR R3,[R10],R6,LSL #netshift
ADD R8,R8,#1
B loop8
.done8
ADD R9,R9,#1
B loop9
.done9
LDMFD R13!,{PC}



.exit
LDMVSFD R13!,{PC}
LDR R1,[R12,#v.basicstack]
CMP R1,R13
BNE stackerr
LDMFD R13!,{PC}

.setup
;claim all the blocks and tables...
STMFD R13!,{R14}
ADD R0,R12,#v.canvas
MOV R1,#320*256
ADR R2,canvasname
MOV R3,#0
SWI Amnesia_ClaimBlock

ADD R0,R12,#v.hellcache
MOV R1,#32*32*18
ADR R2,hellcachename
MOV R3,#0
SWI Amnesia_ClaimBlock

ADD R0,R12,#v.explomap1
MOV R1,#explomaplen*4
ADR R2,explomapname
MOV R3,#0
SWI Amnesia_ClaimBlock

ADD R0,R12,#v.explomap2
MOV R1,#explomaplen*4
ADR R2,explomapname
MOV R3,#0
SWI Amnesia_ClaimBlock

MOV R0,#mastertab
MOV R1,#1
ADR R2,mastertabname
MOV R3,#2
MOV R4,#32
SWI Amnesia_ClaimTable

MOV R0,#backtab
MOV R1,#0
ADR R2,backtabname
MOV R3,#backtablen
MOV R4,#32
SWI Amnesia_ClaimTable

MOV R0,#explotab
MOV R1,#0
ADR R2,explotabname
MOV R3,#256
MOV R4,#32
SWI Amnesia_ClaimTable

MOV R0,#bultab
MOV R1,#1
ADR R2,bultabname
MOV R3,#256
MOV R4,#32
SWI Amnesia_ClaimTable

MOV R0,#specialtab
MOV R1,#1
ADR R2,specialtabname
MOV R3,#64
MOV R4,#36
SWI Amnesia_ClaimTable

MOV R0,#-1
STR R0,[R12,#v.loadedmaster]
STR R0,[R12,#v.loadedbackdrop]
STR R0,[R12,#v.loadedmode]
STR R0,[R12,#v.loadedlevel]
STR R0,[R12,#v.loadedbackpix]
STR R0,[R12,#v.loadeddalek]
STR R0,[R12,#v.loadedspecial]
STR R0,[R12,#v.nutbmog]
MOV R0,#13
STR R0,[R12,#v.mode]
BL setupexplomap
LDMFD R13!,{PC}
.canvasname
DCB "Canvas",0
.hellcachename
DCB "HelCache",0
.mastertabname
DCB "Master",0
.backtabname
DCB "Back",0
.explotabname
DCB "Explo",0
.bultabname
DCB "Bullets",0
.specialtabname
DCB "Special",0
.explomapname
DCB "ExploMap",0
ALIGN



.setupcanvas
;tell FastSpr to write to our canvas, not the screen
STMFD R13!,{R14}
LDR R0,[R12,#v.canvas]
SWI FastSpr_ScreenBank
MOV R0,#0
MOV R1,#0
MOV R2,#320
MOV R3,#192
SWI FastSpr_SetClipWindow
LDMFD R13!,{PC}

.setupscreen
;tell FastSpr to write to the screen
STMFD R13!,{R14}
MOV R0,#0
SWI FastSpr_ScreenBank
MOV R0,#0
MOV R1,#0
MOV R2,#320
MOV R3,#240
SWI FastSpr_SetClipWindow
LDMFD R13!,{PC}

.setupmaster
;set up the player stuff
STMFD R13!,{R14}
MOV R0,#1
STR R0,[R12,#v.master]
LDR R0,[R12,#v.startxpos]
STR R0,[R12,#v.plxpos]
LDR R0,[R12,#v.startypos]
STR R0,[R12,#v.plypos]
MOV R0,#-1
STR R0,[R12,#v.weptimer]
MOV R0,#0
STR R0,[R12,#v.weptype]
MOV R0,#8
STR R0,[R12,#v.health]
MOV R0,#-1
STR R0,[R12,#v.lasthealth]
MOV R0,#mastertab
SWI Amnesia_WipeTable
BL makemaster
LDMFD R13!,{PC}

.setupexplomap
;wipe the explosion map
LDR R1,[R12,#v.explomap1]
MOV R0,#0
MOV R2,#explomaplen
.loopc
STR R0,[R1],#4
SUBS R2,R2,#1
BGT loopc
LDR R1,[R12,#v.explomap2]
MOV R0,#0
MOV R2,#explomaplen
.loopf
STR R0,[R1],#4
SUBS R2,R2,#1
BGT loopf
MOV R0,#0
STR R0,[R12,#v.exploptr]
STR R0,[R12,#v.explomap]
MOV PC,R14


.checkdiscard
STMFD R13!,{R0-R1,R14}
MOV R1,R0
LDR R0,[R0]
CMP R0,#0
SWINE Amnesia_ReleaseBlock
MOV R0,#0
STR R0,[R1]
LDMFD R13!,{R0-R1,PC}

.varsname
DCB "Vars",0
ALIGN
.setupvars
;claims block of memory for the game variables and points R12 to it.
;R12 never changes after this.
STMFD R13!,{R14}
MOV R0,#0
MOV R1,#v.sizeof
ADR R2,varsname
MOV R3,#1; static
SWI XAmnesia_ClaimBlock
BVS nomemoryerr
MOV R12,R0
MOV R0,#0
STR R0,[R12,#v.backdrop]
STR R0,[R12,#v.levelnet]
SWI OS_ReadMonotonicTime
STR R0,[R12,#v.rnseed]
LDMFD R13!,{PC}
;Good grief! Error handling.
.err
LDR R13,[R12,#v.basicstack]
.earlyerr
LDMFD R13!,{R14}
ORR R14,R14,#1<<28
MOVS PC,R14
.nomemoryerr
ADR R0,nomemorytext
B earlyerr
.nomemorytext
DCD &666001
DCB "Insufficient memory in Amnesia area",0
ALIGN
.stackerr
ADR R0,stackerrtext
B err
.stackerrtext
DCD &666002
DCB "Stack mismatch on exit",0
ALIGN
.backrelerr
ADR R0,backrelerrtext
B err
.backrelerrtext
DCD &666
DCB "Back reload error",0
ALIGN
.netwidtherr
ADR R0,netwidtherrtext
B err
.netwidtherrtext
DCD &666
DCB "Unsupported level net width.  use 16,32,64,128 or 256.",0
ALIGN
.vetlevelerr
ADR R0,vetlevelerrtext
B err
.vetlevelerrtext
DCD &666
DCB "Failed to vet level file",0
ALIGN
;These include the precopiled bits in the 'Objects' directory, which
;are created from the files in the 'Sources' directory.
.getfiles
STMFD R13!,{R14}
INCBIN "<Bolmaster$Path>Object.GetFiles"
LDMFD R13!,{PC}

.sortscreen
STMFD R13!,{R14}
INCBIN "<Bolmaster$Path>Object.SortScreen"
LDMFD R13!,{PC}

.readback
STMFD R13!,{R14}
INCBIN "<Bolmaster$Path>Object.ReadBack"
LDMFD R13!,{PC}

.hellshift
INCBIN "<Bolmaster$Path>Object.HellShift"

.bcheck
INCBIN "<Bolmaster$Path>Object.BCheck"

