#type &ffa
#name StasisDeus
#base 0

#set Service_PsychoStarting=&80300
#set Service_PsychoDying   =&80301
#set Service_UKStasisFormat=&80310
#set Service_StasisSave    =&80311
#set Service_StasisIdentify=&80312
#set stasis_alien          =1
#set armadeus_filetype	   =&D3C

.ModuleHeader
.start
DCD 0
DCD init
DCD final
DCD service
DCD title
DCD help
DCD helptable
DCD 0
DCD 0
DCD 0
DCD 0
.title
DCB  "StasisDeus"
DCB 0
ALIGN
.help
DCB  "Stasis Alien",9,"1.00 (24 Jan 1995) - For logarithmic Armadeus samples"
DCB 0
ALIGN
.helptable
DCB  "StasisDeus"
DCB 0
ALIGN
DCD 0
DCD 0
DCD 0
DCD rawhelp
DCD 0;End Marker
.rawhelp
DCB "This module allows Stasis to handle logarithmic Armadeus samples.  The samples can be replayed, and saved by the *StasisSave Armadeus command.",0
ALIGN
.service
;R12 is the only register we may corrupt in a service call
SUBS R12,R1,#&80000
MOVMI PC,R14
SUB R12,R12,#&300
TEQ R12,#Service_UKStasisFormat-&80300
TEQNE R12,#Service_StasisIdentify-&80300
TEQNE R12,#Service_StasisSave-&80300
MOVNE PC,R14
TEQ R12,#Service_StasisIdentify-&80300
BEQ identify
TEQ R12,#Service_StasisSave-&80300
BEQ save
.ukformat
STMFD R13!,{R3-R4,R14}
MOV R4,#armadeus_filetype
CMP R2,R4
LDMNEFD R13!,{R3-R4,PC}^
;identified an armadeus by its filetype.
ADR R0,alienblock
MOV R1,#0; claim service call
LDMFD R13!,{R3-R4,PC}

.alienblock
DCB "StAl"; ID Word - required - used to check if the block is valid.
DCD getinfo-alienblock;get info routine
DCD putinfo-alienblock;put info routine
DCD 0     ;release routine (we don't have one)
DCD 0     ;must be zero
DCD 0     ;for future use
DCD 0     ;for future use
DCD name1-alienblock
DCD formatname-alienblock
DCD armadeus_filetype
DCD title-alienblock
DCD 0
ALIGN

;The info routine is entered with
;R0 points to the stasis slot decription block
;R1 points to your sample

;The file length as loaded may be accessed by LDR R0,[R10,#4]

;The info entry should return:

;R1=name *
;R2=length
;R3=finetune * &4000=default, &2000=1 octave lower, &8000=1 octave higher etc 
;R4=repofs *
;R5=replen *
;R6=datastart
;R7=volume *
;R8=special (return R8=0)
; *= may return zero if not supported

.getinfo
MOV R11,R1;our sample address
MOV R1,#0; sample name - not supported
LDR R2,[R10,#4]; file length
SUB R2,R2,#1
LDRB R5,[R11]  ;get the sample period
MOV R4,#&4000*48; finetune &4000 for sample period of 48us
MYDIV R3,R4,R5 ; MYDIV is a macro - see end of file
MOV R4,#0
MOV R5,#0
MOV R7,#0
ADD R6,R11,#1; skip the first byte - it's the sample rate
MOV R7,#0
MOV R8,#0
MOV PC,R14

.putinfo
AND R0,R8,#%111111111         ;what we don't support ie everything
MOV PC,R14

.identify
ADD R0,R0,#1
CMP R2,#0
MOVEQ PC,R14
ADR R12,alienblock
STR R12,[R2],#4
MOV PC,R14

;On entry to a save routine, R0 is the slot number (for us to pass
;to Stasis_GetSlotInfo.
;R2 points to the filename
;R3 points to the namecheck routine in Stasis which compares the name
;pointed to by R1 to that entered at the command line

;We pass on the Service call if we don't recognise the save type
;ie return with MOV PC,R14 with registers unchanged.
;If we want to save in our format we return with
;R0 preserved.
;R1=0 to claim the service call
;R2 points to a filled-in header block
;R3 is the length of the header block
;R4 is the filetype
;Stasis will add the sample data in logarithmic format after the header
;
;Otherwise return with R2=0 after carrying out the whole save process
;yourself.
;To return an error, return with R2=1 and R0 pointing to an error block.

.armadeusformat
DCB 0  ;sample period
ALIGN
.save
STMFD R13!,{R1,R14}
ADR R1,name1
MOV R14,PC
MOV PC,R3       ;BL to R3
BEQ goforsave
ADR R1,name2
MOV R14,PC
MOV PC,R3
.goforsave
LDMFD R13!,{R1,R14}
MOVNES PC,R14;return if no match
STMFD R13!,{R0,R5-R10,R14}
SWI Stasis_GetSlotInfo  ;get finetune value into R3
MOV R0,#&4000*48
MYDIV R1,R0,R3
CMP R3,#0
MOVEQ R3,#48
ADR R0,armadeusformat
STRB R1,[R0]

MOV R1,#0
ADR R2,armadeusformat
MOV R3,#1
MOV R4,#armadeus_filetype
LDMFD R13!,{R0,R5-R10,PC}
;return and let Stasis do the rest

.init                  ;My standard init/final service calls.
STMFD R13!,{R0-R3,R14}
ADR R0,start
MOV R1,#Service_PsychoStarting
MOV R2,#0; the R12 value
MOV R3,stasis_alien
ADR R4,alienblock
SWI OS_ServiceCall
CMP R1,#0
LDMFD R13!,{R0-R3,R14}
ADREQ R0,initerrtext
ORRVS R14,R14,#1<<28
MOVS PC,R14

.final
STMFD R13!,{R0-R3,R14}
ADR R0,start
MOV R1,#Service_PsychoDying
MOV R2,#0
MOV R3,stasis_alien
ADR R4,alienblock
SWI OS_ServiceCall
CMP R1,#0
LDMFD R13!,{R0-R3,R14}
ADREQ R0,finalerrtext
ORRVS R14,R14,#1<<28
MOVS PC,R14

.oldstasiserr
STMFD R13!,{R14}
SWI OS_WriteS
DCB "StasisDeus : Stasis module too old to load this type of file",10,13,0
ALIGN
LDMFD R13!,{PC}

.initerrtext
DCD &809DFE
DCB "StasisDeus : Initialisation veto",0
ALIGN
.finalerrtext
DCD &809DFF
DCB "StasisDeus : RMKill veto",0

.name1
DCB "Armadeus",0
.name2
DCB "Deus",0
.formatname
DCB "Armadeus",0
ALIGN



macro MYDIV m0,m1,m2,t0
{
TST R13,#3
MOVNE PC,#0
CMP m1,#0
RSBLT m1,m1,#0
EORLT R13,R13,#1
CMP m2,#0
RSBLT m2,m2,#0
EORLT R13,R13,#2
BNE _MYDIV4
CMP m1,#0
MOVEQ m0,#0
MOVNE m0,#&7f000000
B _MYDIV1
._MYDIV4
MOV t0,#1
._MYDIV2
CMP m2,#&80000000
CMPCC m2,m1
MOVCC m2,m2,LSL #1
MOVCC t0,t0,LSL #1
BCC _MYDIV2
MOV m0,#0
._MYDIV3
CMP m1,m2
SUBCS m1,m1,m2
ADDCS m0,m0,t0
MOVS t0,t0,LSR #1
MOVNE m2,m2,LSR #1
BNE _MYDIV3
._MYDIV1
TST R13,#2
RSBNE m2,m2,#0
TST R13,#1
RSBNE m1,m1,#0
EORNE R13,R13,#2
TST R13,#2
RSBNE m0,m0,#0
BIC R13,R13,#3
}





