***************************************
*                                     *
* Make a list of prime numbers. It    *
* should work up to 4,294,967,295     *
*                                     *
* written by E. Lenz                  *
*            Johann-Fichte-Strasse 11 *
*            8 Munich 40              *
*            Germany                  *
*                                     *
***************************************


_AbsExecBase     equ 4

*****EXEC*******

_LVOForbid       equ -$84
_LVOPermit       equ -$8a
_LVOAllocMem     equ -$c6
_LVOFreeMem      equ -$d2
_LVOGetMsg       equ -$174
_LVOReplyMsg     equ -$17a
_LVOWaitPort     equ -$180
_LVOCloseLibrary equ -$19e
_LVOOpenLibrary  equ -$228

*****DOS*****

_LVOOpen         equ -$1e
_LVOClose        equ -$24
_LVOWrite        equ -$30

TC_SIGRECVD      equ $1a
pr_MsgPort       equ $5c
pr_CLI           equ $ac
ThisTask         equ $114
VBlankFrequency  equ $212 
MODE_OLDFILE     equ 1005
MODE_NEWFILE     equ 1006
SIGBREAK_ANY     equ $1000

; INTERNALLY USED
;
; d3 buffer size
; d4 file handler
; d5 DosBase
; d6 console handler
; d7 buffer address
; a4 pointer to next entry in buffer

          move.l  d0,d4    save CLI parameters
          movea.l a0,a4

          movea.l _AbsExecBase,a6   test if WB or CLI
          movea.l ThisTask(a6),a0
          lea     TC_SIGRECVD(a0),a1
          move.l  a1,TaskSigs        get task signal address
          moveq   #0,d0
          tst.l   pr_CLI(a0)
          bne.s   isCLI

          moveq   #1,d4             no parameter
          lea     pr_MsgPort(a0),a0 for WB get WB Message
          jsr     _LVOWaitPort(a6)
          jsr     _LVOGetMsg(a6)

isCLI     move.l  d0,-(a7)
          lea     window(pc),a3
          cmpi.b  #60,VBlankFrequency(a6) test if PAL or NTSC
          beq.s   isNTSC
          movea.l a3,a0
          addq.l  #8,a0
          addq.l  #4,a0
          move.l  #'256/',(a0)

isNTSC    move.l  #$6700,d0         allocate buffer
          move.l  d0,d3             save buffer size
          move.l  #$30000,d1        largest + clear
          jsr     _LVOAllocMem(a6)
          move.l  d0,d7
          beq.s   exit

          lea     dosname(pc),a1    open DOS library
          moveq   #0,d0
          jsr     _LVOOpenLibrary(a6)
          move.l  d0,d5
          beq.s   exit

          movea.l d0,a6             open Console window
          move.l  a3,d1
          move.l  #MODE_OLDFILE,d2
          jsr     _LVOOpen(a6)
          move.l  d0,d6
          beq.s   exit

          subq.l  #1,d4            open output file if named on 
          beq.s   doPrime          command line
          movea.l a4,a0
find      cmpi.b  #$a,(a0)+
          bne.s   find
          clr.b   -(a0)
          move.l  a4,d1
          move.l  #MODE_NEWFILE,d2
          jsr     _LVOOpen(a6)
          move.l  d0,d4

** start off with the prime number 3 ***

doPrime   movea.l d7,a4
          moveq   #3,d0
          move.l  d0,(a4)+
prlop     bsr.s   ShowPrime
          bsr     NextPrime

          movea.l TaskSigs(pc),a0
          move.l  (a0),d1
          andi.l  #SIGBREAK_ANY,d1
          bne.s   exit

          tst.l   d0
          bne.s   prlop
 
exit      tst.l   d5
          beq.s   free
          move.l  d6,d1             close console
          beq.s   error
          jsr     _LVOClose(a6)

          move.l  d4,d1             close file
          beq.s   free
          jsr     _LVOClose(a6)

free      movea.l _AbsExecBase,a6
          tst.l   d7                free buffer
          beq.s   error
          movea.l d7,a1
          move.l  d3,d0
          jsr     _LVOFreeMem(a6)

error     move.l  (a7)+,d7
          beq.s   NoBench
          jsr     _LVOForbid(a6)    reply to WB
          movea.l d7,a1
          jsr     _LVOReplyMsg(a6)
          jsr     _LVOPermit(a6)

NoBench   tst.l   d5
          beq.s   nodos
          movea.l d5,a1            close dos.lib
          jsr     _LVOCloseLibrary(a6)
nodos     moveq   #0,d0
          rts

********************************************
*                                          *
* Write number in d0 as decimal to console *
*                                          *
********************************************


ShowPrime movem.l d0-d3/a0-a1,-(a7)
          lea     Prime(pc),a1
          movea.l a1,a0
          move.l  #'0000',d1
          move.l  d1,(a1)+
          move.l  d1,(a1)+
          move.b  #$a,d1
          move.l  d1,(a1)+
          lea     Num(pc),a1
plop      move.l  (a1)+,d1
          addq.l  #1,a0
pnext     cmp.l   d1,d0
          bcs.s   plop
          sub.l   d1,d0
          addq.b  #1,(a0)
          tst.l   d0
          bne.s   pnext
          lea     Prime(pc),a0
          moveq   #12,d3
ptest     cmpi.b  #'0',(a0)
          bne.s   endp
          subq.l  #1,d3
          addq.l  #1,a0
          bra.s   ptest
endp      move.l  a0,d2
          move.l  d6,d1
          movem.l d2-d3,-(a7)
          jsr     _LVOWrite(a6)
          movem.l (a7)+,d2-d3
          move.l  d4,d1
          beq.s   nofile
          jsr     _LVOWrite(a6)
          tst.l   d0                  disk full?
          bne.s   nofile
          movem.l (a7)+,d0-d3/a0-a1
          moveq   #-1,d0              end of programme
          rts
nofile    movem.l (a7)+,d0-d3/a0-a1
          rts

******************************************
*                                        *
* Calculate next prime number            *
*                                        *
******************************************

NextPrime move.l  d7,a0
          addq.l  #2,d0
          bcs.s   eprim
nlop      move.l  (a0)+,d2
          beq.s   isPrime
          move.l  d2,d1
          mulu    d2,d1
          cmp.l   d1,d0
          bcs.s   isPrime
          bsr.s   mod
          tst.l   d2
          beq.s   NextPrime     no prime - try next number
          bra.s   nlop          try next divisor
isPrime   move.l  d0,d1
          swap    d1
          tst.w   d1
          bne.s   nosave
          move.l  d0,(a4)+
nosave    rts
eprim     moveq   #0,d0
          rts

**************************
*                        *
* return d0 mod d2 in d2 *
*                        *
**************************

mod       move.l  d0,-(a7)
          lea     pow(pc),a1
          moveq   #9,d1
mlop      move.l  d2,(a1)+
          add.l   d2,d2
          dbra    d1,mlop
mnext     move.l  -(a1),d1
          beq.s   mend
mwhat     cmp.l   d1,d0
          bcs.s   mnext
          sub.l   d1,d0
          beq.s   mend
          bra.s   mwhat
mend      move.l  d0,d2
          move.l  (a7)+,d0
          rts

TaskSigs  ds.l 1
Num       dc.l 1000000000,100000000,10000000,1000000,100000,10000,1000,100,10,1
Prime     ds.b 12

          dc.l 0
pow       ds.l 1

dosname   dc.b 'dos.library',0
          even

window    dc.b 'CON:0/0/200/200/Prime numbers',0
          even
          end

