;Most of these routines are subroutines which I used in my lates program SecureIt-85
;I don't wish to release the actual code for the program at this point (there are still
;some bugs I must fix) but I thought that others might learn from some of the routines
;I used.  Do what you wish with them, but if you use them in any major program, please
;give me some credit!  Just remember, I don't gaurantee that the routines will work
;perfectly, and don't accept any responsibility for any use and/or misuse of these
;routines.  Feel free to e-mail me any questions about the code.
;
;Thanks,
;Michael Wyman
;wyma0012@gold.tc.umn.edu
;
;*************************************************************************************

;Input password to dummy string (hl must point to dummy string,
;relatively).  If Key gotten is exit, loop quits with a value
;in accumulator.
GetPass:
 push	hl			;save original hl address
 ld	hl, $1100		;print Password prompt at (x,y)=($00,$11)
 ld	($8333), hl		;
 ld	hl, Prompt		;
 CALL_(DispMenu)		;display prompt
 pop	hl			;return original hl address
GetWordStuff:
 ld	de, (PROGRAM_ADDR)	;find absolute address of string pointed to by hl
 add	hl, de			;
 ld	b, $0a			;length of string is $a
 push	hl			;store absolute address of string
 CALL_(FillLoop)		;fill string with $00 (see subroutine below)
 pop	hl			;restore absolute address of string
 ld	b, $0a			;length of string is $a
Getkys:
 CALL_(WaitKey)			;Wait for keypress (easy routine, just remember to keep hl safe)
 cp	(K_EXIT)		;check if key pressed is EXIT
 jr	z, Exited		;exit loop if key was EXIT
 ld	(hl), a			;store key pressed in (hl)
 inc	hl			;increase string pointer hl
 cp	(K_ENTER)		;check if key pressed is ENTER (meaning done)
 jr	z, DoneNowPass		;exit loop if key was ENTER
 djnz	Getkys			;repeat if b isn't zero
DoneNowPass:
 ld	a, $00			;password was entered fully
 ret				;return from subroutine
Exited:
 ld	a, $0f			;password was not entered fully
 ret				;return from subroutine

;Compares strings pointed to by relative addresses (hl) and (de) with
;each other (given their length in b).  Returns a value if they don't
;match, and $00 if to do match in register a.
Compare:
 push	bc			;store length of strings to compare
 ld	bc, (PROGRAM_ADDR)	;find absolute address of strings
 add	hl, bc			;
 ex	de, hl			;
 add	hl, bc			;
 pop	bc			;return length of strings to compare to b
CompareNow:
 ld	a, (hl)			;load value in (hl) to acc
 ld	c, a			;load acc into c
 ex	de, hl			;exchange addresses de and hl
 ld	a, (hl)			;load values in (hl) to acc
 ex	de, hl			;return addresses to proper registers
 cp	c			;compare acc to c
 jr	nz, NotEqual		;jump to NotEqual if acc is inequal to c
NotDoneYet:
 or	a			;find if acc and c are zero
 jr	z, DoneYet		;if they are, you are done (they are zero terminated)
 inc	de			;increase address pointer de
 inc	hl			;increase address pointer hl
 djnz	CompareNow		;compare the next pairs of data
DoneYet:
 ld	a, $00			;the strings are equal
 ret				;return from subroutine
NotEqual:
 ld	a, $0f			;the strings are inequal
 ret				;return from subroutine

;Fills String pointed to by absolute (hl) with null's (must have
;length of string in b).
FillLoop:
 ld	a, 0			;load $00 into acc
FillLoop1:
 ld	(hl), a			;load acc into address (hl)
 inc	hl			;increase hl
 djnz	FillLoop1		;repeat until b equals zero
 ret

;Copies string pointed to by relative (hl) to that pointed to by
;relative (de), length b.  Returns updated (de).
Copy:
 push	bc			;store values in bc in the stack
 ld	bc, (PROGRAM_ADDR)	;load into bc the Prog. addr.
 add	hl, bc			;find absolute address of first string
 ex	de, hl			;exchange values from de to hl
 add	hl, bc			;find absolute address of second string
 ex	de, hl			;return original values to the proper registers
 pop	bc			;return string length to b
CopyNow:
 ld	a, (hl)			;load value from (hl) to acc
 or	a			;find whether acc is zero
 jr	z, DoneCopy		;if acc is zero, exit loop
 ex	de, hl			;exchange addresses from de to hl
 ld	(hl), a			;load acc into address pointed to by hl
 ex	de, hl			;return original values to the proper registers
 inc	de			;increment de
 inc	hl			;increment hl
 djnz	CopyNow			;decrease b and return to CopyNow if b isn't zero
DoneCopy:
 ret

;*******************************************************************
;This routine is not from SecureIt-85, but just an idea for a self-encrypting
;program which I decided to write down.
;*******************************************************************
;This routine is a routine which will xor $ff every byte of a program
;at the beginning to decrypt the program, and at the end to encrypt
;the program.
 ld	hl, Encrypt_Loop	;load relative address of Encrypt_Loop
 ld	de, Encrypted_Byte	;load relative address of Encrypted_Byte
 sbc	hl, de			;find the # of bytes in main program
 ex	de, hl			;exchange de and hl, (so we can use hl again)
 push	de			;store the amount of bytes in main program
 ld	bc, (PROGRAM_ADDR)	;load program address into bc
 add	hl, bc			;find absolute address of beginning of main program
 push	hl			;store absolute address of beginning of main program
 ld	a, (hl)			;check to see if program is encrypted or not (mainly for first time use of program only)
 cp	$0f			;
 jr	z, Prog_Start		;jump to the beginning of the program if it isn't encrypted
Decrypt_Loop:
 ld	a, (hl)			;opcodes of program into acc
 xor	$ff			;xor $ff the stored value
 ld	(hl), a			;return the value to the memory location it occupied
 inc	hl			;increase hl to point to the next byte
 dec	de			;decrease de to determine how many more bytes must be decrypted
 jr	nz, Decrypt_Loop	;jump to Decrypt_Loop if de isn't zero
 jr	Prog_Start		;go to the beginning of the program
Encrypted_Byte
.db $0f				;just to tell whether the program is encrypted or not
;*********************************************
;Main body of program here
;*********************************************
Encrypt_Start:
 pop	hl			;load absolute address Encrypt_Byte into hl
 pop	bc			;load # of bytes to be encrypted
Encrypt_Loop:
 ld	a, (hl)			;Load value to be encrypted
 xor	$ff			;encrypts value by XOR $ff
 ld	(hl), a			;place encrypted opcode where the unencrypted value occupied
 inc	hl			;increase pointer
 dec	bc			;decrease by one the number of opcodes left to be encrypted
 jr	nz, Encrypt_Loop	;jump to Encrypt_Loop if bc isn't zero
 ld	hl, ZS_BITS		;Have ZShell checksum the program again
 set	0, (hl)			;
 ret
