;       My contribution to randon number generators     (by Risto Jвvinen)
;       -------------------------------------------
;
;   Here's two simple 16-bit random number generators.  I originally made
; them on PC but since ZShell doesn't support ROM-random generator I converted
; them to Z80.
;   My generators were kind of quick'n'dirty hacks on PC, but acceptable on
; Z80.  Their advantage was their small size, but on Z80-assembler they are
; giant-sized.  If you (too) think that these generators are wasting TI's
; resources use random generators provided by Chris Busch (rand.asm found on
; many ZShell-sites).
;   I still use the first generator with demo coding (on PC).  It uses two
; 16-bit seeds.  It rotates first seed three bits left and adds some trash
; bits then it rotates second seed (first seed and %1111) bits left and adds
; some trash bits.  Easy and compact on PC, quite a gonzo-routine on Z80. This
; could be considered as resource wasting on TI.  The second generator uses
; only the first seed of the first generator.
;   Both generators start with zeroed seed(s).  If you wish to use randoms for
; anything make your program save & restore seed(s) upon leaving & entry.
;   This program demonstrates the random generators.  It calls generators and
; shows lowest 8-bits of result.  Press F1 to use high-quality generator and
; F2 to use low-quality version.  Generators have seperated seed so they don't
; mess up each other.  When you've played with it enough press EXIT.
;   And last but not least: It's RibaWare; no copyright, 100% public domain.
; All rights wronged, all wrongs reversed.  Learn'n'Copy!
;
;   I, Risto Jвvinen, don't have my own email address so if you wish to
; contact me please use my friends address:
;
;       Jarno_Uurainen@llauta.fipnet.fi
;
;         +------------------------------+
;   NOTE: | DO NOT SEND ANY BIG FILES!!! |
;         +------------------------------+
;   One idiot sent to my friend a 2meg .WAV!  He receives his email via
; a BBS so sending mega-email causes messagepolling to take forever and
; sysop to go nuts.  If mega-stuff pops up place it on FTP and I'll leech
; it someday...  I don't think that You're an idiot (after all you propably
; have TI's calculator).  This is just a precaution :)
;

#include "TI-85.H"      ; Uses extended ZShell header

;   Variables for random generators
seed1   = $80df         ; I Seed for 2x16bit generator
seed2   = $80e1         ; II Seed for 2x16bit generator

seed    = $80e3         ; Seed for 16bit generator


.org    0
.db     "Random numbers",0

   ROM_CALL(CLEARLCD)

   res 1,(IY+0D)                ;don't scroll the text memory!!!

   ld   de,0
   ld   (CURSOR_ROW),de         ;Setup textpointers
   ld   d,10
   ld   (CURSOR_X),de

   ld   hl,(PROGRAM_ADDR)
   ROM_CALL(D_ZT_STR)           ;Display title string (Text-font)

   ld   hl,(PROGRAM_ADDR)
   ld   de,instruct
   add  hl,de
   ROM_CALL(D_ZM_STR)           ;Display instructions (Menu-font)

keyloop:
   call GET_KEY                 ;Get pressed key
   cp   K_Exit                  ;Check if EXIT...
   ret  z                       ;...then return to ZShell

   cp   K_F2                    ;Check if F2...
   jr   z,rnd2
   cp   K_F1                    ;Check if F1...
   jr   nz,keyloop
   CALL_(random1)
   ld   hl,(seed1)
   ld   d,3
   jr   display
rnd2:
   CALL_(random2)
   ld   hl,(seed)
   ld   d,9
display:
   ROM_CALL(SCROLL_UP)          ;Scroll screen
   ld   e,6                     ;Set cursor row to 6
   ld   (CURSOR_ROW),de
   ld   h,0
   ROM_CALL(D_HL_DECI)          ;Display 8 lowest bits
   jr   keyloop


instruct:
.db     "F1 = 2*16bit,   "
.db     "F2 = 16bit,   "
.db     "EXIT = Exit",0


;       High quality 2x16-bit seed random number generator
;       --------------------------------------------------
;   May be slow but sure is 'random'.
;   Routine uses two 16-bit variables, seed1 and seed2.
;   Read and cut the result out of seed1.

;asm    { Original 286-code, I've made this on TP7... }
;   mov   ax,[seed1]
;   mov   cx,[seed2]
;   rol   cx,3
;   add   cx,$7415
;   mov   [seed2],cx
;   rol   ax,cl
;   add   ax,$6349
;   mov   [seed1],ax
;end;   { Returns random byte in al (or word in ax) }

random1:
   push hl                      ;Stores registers
   push bc                      ;Remove if unnecessary in Your program
   push af

   ld   hl,(seed2)              ;Load seed2 to HL
   ld   a,h
   add  a,a                     ;Set highest bit of seed to carry
   rl   l                       ;rotate L left (C<=L<=C)
   rl   h                       ;rotate H left (C<=L<=C)
   add  a,a                     ;Set second highest bit of seed to carry
   rl   l
   rl   h
   add  a,a
   rl   l
   rl   h
   ld   bc,$7415
   add  hl,bc                   ;Add $7415 to HL
   ld   (seed2),hl              ;Load seed2 with HL

   ld   a,l                     ;Preserve L
   ld   hl,(seed1)              ;Load seed1 to HL
   and  %00001111
   jr   z,norot
   ld   b,a
rotmore:                        ;Rotate HL (a and %1111) bits
   add  hl,hl                   ;Z80-version of 16-bit rotate!
   jr   nc,notinc
   set  0,l
notinc:
   djnz rotmore
norot:
   ld   bc,$6349                ;Add $6349 to HL
   add  hl,bc
   ld   (seed1),hl              ;Load seed1 with HL

   pop  af                      ;Restores registers
   pop  bc
   pop  hl
   ret


;       16-bit seed random generator
;       ----------------------------
;  Faster than previous routine.
;  Uses only one 16-bit variable, seed.
;  Read and cut the result out of variable seed.
random2:
   push hl                      ;Stores registers
   push bc                      ;Remove if unnecessary in Your program
   push af

   ld   hl,(seed)               ;Load seed to HL
   ld   a,h
   add  a,a                     ;Set highest bit of seed to carry
   rl   l                       ;rotate L left (C<=L<=C)
   rl   h                       ;rotate H left (C<=L<=C)
   add  a,a                     ;Set second highest bit of seed to carry
   rl   l
   rl   h
   add  a,a
   rl   l
   rl   h
   ld   bc,$7415
   add  hl,bc                   ;Add $7415 to HL
   ld   (seed),hl               ;Load seed with HL

   pop  af
   pop  bc
   pop  hl
   ret


.end
