;	  RANDOM.COM		       Designed and written by Wilson Seto
;	  Version 1.10		       Inspired by Nathan Hull and Ettiene Martin
;				       Idea borrowed from TURBO C & PASCAL
;
;	  Terminate and stay resident random number generator.
;
;	  HOW TO ASSEMBLE:	       tasm random.asm
;
;	  HOW THIS WORKS: First check to see if already installed, if not then
;	  do so, else abort.  Print the appropriate message.  To get a random
;   number do an INT 62H with AX equal to the desired range value.
;	  The random number is created by shifting, adding, multiplying, and
;	  dividing the seed values.  The number returned in AX is between
;	  0 and the range value, all other registers are unchanged.
page	 60,130
cseg	  segment
assume cs:cseg, ds:cseg
assume es:cseg, ss:cseg
org	 100h
start:	  jmp	 short check
;---------TSR routine-----------------------------------------------------------
constant  dw	 8405h		       ;multiplier value
seed1	  dw	 ?
seed2	  dw	 ?		       ;random number seeds
int_62h   proc   far
or	 ax,ax		       ;range value <> 0?
jz	 abort		       ;if not then abort
push	 bx
push	 cx
push	 dx
push	 ds
push	 ax		       ;save the range value
push	 cs
pop	 ds		       ;ds = cs
mov	 ax,seed1
mov	 cx,ax		       ;save seed
mul	 constant	       ;(dx,ax) = ax * constant
shl	 cx,1
shl	 cx,1
shl	 cx,1
shl	 bx,1		       ;begin scramble algorithm
shl	 bx,1
mov	 cl,5
shl	 bx,cl
mov	 seed1,ax
mov	 seed2,dx	       ;save results as the new seeds
pop	 bx		       ;get back range value
xor	 ax,ax		       ;clear register
div	 bx		       ;ax = trunc((dx,ax) / bx), dx = (r)
xchg	 ax,dx		       ;return remainder as the random number
pop	 ds
pop	 dx
pop	 cx
pop	 bx
int_62h   endp
;-------------------------------------------------------------------------------

;---------Initialization routine------------------------------------------------
check:	  mov	 ax,3000h	       ;get DOS version
int	 21h
cmp	 al,3		       ;DOS version 3.0 or higher?
jae	 chk_vec
mov	 dx,offset wrong_dos   ;incorrect DOS version, inform user
quit:	  mov	 ah,9
int	 21h
int	 20h		       ;back to DOS
chk_vec:  mov  ax,3562h        ;get interrupt vector for int 62h - es:bx
int	 21h
mov  di,bx           ;es:di points to int 62h
mov  si,offset int_62h     ;point to our copy of int 62h
mov	 cx,16		       ;# of bytes to compare
cld			       ;forward string movement
repe	 cmpsb		       ;compare memory regions
jnz	 install	       ;if not identical then not installed
jmp	 short quit
install:  mov	 ah,2ch 	       ;get current time
int	 21h
mov	 seed1,cx
mov	 seed2,dx	       ;save as initial seeds
int	 21h
mov  dx,offset int_62h     ;point to routine to install - ds:dx
mov  ax,2562h        ;change interrupt 62h vectors
int	 21h
mov	 dx,offset check       ;end of resident code
int	 27h		       ;TSR
;-------------------------------------------------------------------------------

;---------Data area-------------------------------------------------------------
wrong_dos db     13,10,10,'Requires DOS V3.0 or higher!',13,10,10,7,7,36