*  stars.asm - by A. Tuline
*  revised for the Gibbs A68k Assembler by Tom Eshelman
*  This assembler demands labels in column 1 - period!

   INCLUDE "exec/types.i"
   INCLUDE "intuition/intuition.i"
   INCLUDE "graphics/rastport.i"
   INCLUDE "exec/ports.i"

* Macros

SYS      MACRO
           JSR      _LVO\1
         ENDM


* exec calls

         EXTERN_LIB  OpenLibrary             ; (libName,version)(A1,D0)
         EXTERN_LIB  CloseLibrary            ; (libbNode)(A1)
         EXTERN_LIB  GetMsg                  ; (msgPort)(D0)
         EXTERN_LIB  ReplyMsg                ; (message)(A1)
         EXTERN_LIB  Wait                    ; (signalSet)(D0)

* intuition calls

         EXTERN_LIB  OpenWindow              ; (newWindow)(A0)
         EXTERN_LIB  CloseWindow             ; (Window)(A0)
         EXTERN_LIB  OpenScreen              ; (newScreen)(A0)
         EXTERN_LIB  CloseScreen             ; (Screen)(A0)
         EXTERN_LIB  ShowTitle               ; (Screen,ShowIt)(A0,D0)

* graphics calls

         EXTERN_LIB  Draw                    ; (rp,x,y)(A1,D0,D1)
         EXTERN_LIB  Move                    ; (rp,x,y)(A1,D0,D1)
         EXTERN_LIB  ReadPixel               ; (rp,x,y)(A1,D0,D1)
         EXTERN_LIB  SetAPen                 ; (rp,pennum)(A1,D0)
         EXTERN_LIB  SetDrMd                 ; (rp,drawmode)(A1,D0)
         EXTERN_LIB  SetRGB4       ;(viewPort,register,r,g,b)(A0,D0/D1/D2/D3)
         EXTERN_LIB  WritePixel              ; (rp,x,y)(A1,D0,D1)
         EXTERN_LIB  SetRast                 ; (rp,pennum)(A1,D0)

* externally defined variables

         XREF     _AbsExecBase            ; see amiga.lib



******************************
*  Start of Code             *
******************************

startup:

      move.l     a7,savesp             ;save present stack ptr for return.

      movea.l   _AbsExecBase,a6        ;move into Sysbase
      lea.l      IntLibArgs,a1         ;args into a1
      moveq      #0,d0                 ;any version 
      SYS        OpenLibrary(a6)       ;open Intuition Library
      move.l     d0,IntBase            ;save this library base
      beq        openerr

* Open Graphics Library

      movea.l   _AbsExecBase,a6
      lea.l      GrafLibArgs,a1
      moveq      #0,d0
      SYS        OpenLibrary(a6)
      move.l     d0,GrafBase           ;save this library base too.
      beq        openerr

* Open a screen


      movea.l  IntBase,a6
      lea      screenvars,a0
      SYS      OpenScreen(a6)
      move.l   d0,newscreenptr          ;save the ptr to our screen
      beq      openerr

      add.l    #sc_RastPort,d0          ;find rastport offset
      move.l   d0,myraster              ;save a pointer to the rastport
      sub.l    #sc_RastPort,d0          ;return to the screen ptr.
      add.l    #sc_ViewPort,d0          ;find viewport offset
      move.l   d0,myview                ;save pointer to the viewport

      movea.l  IntBase,a6               ;hide the screentitle routine
      move.l   newscreenptr,a0
      move.l   #0,d0                    ;cause it to be hidden
      SYS      ShowTitle(a6)

* Open a window

      movea.l  IntBase,a6
      lea      windowvars,a0
      SYS      OpenWindow(a6)
      move.l   d0,newwindowptr          ;save ptr to our new window
      beq      openerr


setcolours:

* Set the background to black and the other to blue.

      movea.l   GrafBase,a6
      movea.l   myview,a0
      move.l    #0,d0                   ; set color register 0 to:
      moveq     #0,d1                   ; red   +
      moveq     #0,d2                   ; green +----> black
      moveq     #0,d3                   ; blue  +
      SYS       SetRGB4(a6)

      move.l    GrafBase,a6
      move.l    myview,a0
      move.l    #1,d0                    ; set color register 1 to:
      move.b    #10,d1                   ; red   +
      move.b    #10,d2                   ; green +----> blue
      move.b    #15,d3                   ; blue  +
      SYS       SetRGB4(a6)


* Set the drawing mode

      movea.l  GrafBase,a6
      movea.l  myraster,a1
      move.b   RP_JAM1,d0
      SYS      SetDrMd(a6)

* At this point, at least the screen and window are set up well enough
* to work without too much fuss.  TJE  1/12/88
* I don't like unusual jsr calls.   Hence, the revision.


starinstall:

      lea      pont,a3              ;an array of 1024 data bytes
      lea      pontend,a4           ;a4 holds address of 1 byte of data


redostars:

      jsr      starun
      jsr      getmsg                  ; d0 has pointer to message
;      jsr      replymsg
      tst.l    d0
      beq      redostars               ; jump back if no message pointer

      move.l   d0,a0
      move.l   im_Class(a0),d0
      andi.l   #CLOSEWINDOW,d0
      beq      redostars               ; jump back if not CLOSEWINDOW msg

*         jsr      replymsg                ; should be right after getmsg

stopprog:

      jsr      closeall

exitprog:

      movea.l   savesp,a7
      rts

**********************************
*  End of program. 'main'.
**********************************


newstars:

         jsr      point_maker
         add.w    #lenth,a3
         cmpa.l   a4,a3
         blt      newstars                ;infinite loop.

         move.b   #1,speed                ; initialize various parmeters
         move.w   #160*64,x_centre
         move.w   #99*64,y_centre
         move.w   #0,x_abs
         move.w   #0,y_abs

         rts


starun:
      lea      pont,a3
      lea      pontend,a4

starup:
      move.b   speed,d4
      move.w   xold_st(a3),d2
      move.w   d2,d5
      sub.w    x_centre,d5
      asr.w    d4,d5                   ; shift delx by speed factor

      move.b   dx_st(a3),d4
      asr.w    d4,d5                   ; distance across factor

      add.w    d5,d2
      sub.w    x_abs,d2
      sub.w    x_abs,d2

      cmp.w    #x_rang,d2
      bcc      str_out_rang
      cmp.w    #xlower,d2
      bls      str_out_rang

      move.w   d2,xnew_st(a3)

      move.b   speed,d4

      move.w   yold_st(a3),d2          ; d2 <- yold
      move.w   d2,d5
      sub.w    y_centre,d5
      asr.w    d4,d5

      move.b   dx_st(a3),d4
      asr.w    d4,d5

      add.w    d5,d2
      sub.w    y_abs,d2
      sub.w    y_abs,d2

      cmp.w    #y_rang,d2
      bcc      str_out_rang
      cmp.w    #ylower,d2
      bls      str_out_rang

      move.w   d2,ynew_st(a3)

      move.w   xold_st(a3),d0          ; preset old point
      move.w   yold_st(a3),d1
      bsr      preset

      move.w   xnew_st(a3),d0          ; pset new point
      move.w   ynew_st(a3),d1
      bsr      pset

      move.w   xnew_st(a3),xold_st(a3)
      move.w   ynew_st(a3),yold_st(a3)

      bra      next_star


str_out_rang:

         move.w   xold_st(a3),d0
         move.w   yold_st(a3),d1
         bsr      preset
         bsr      point_maker

next_star:
         add.w    #lenth,a3
         cmpa.l    a4,a3
         blt      starup

starend:
         rts


preset:

         move.l   d0,d3
         move.l   d1,d4
         move.b   #0,d0                   ; 0 = black
         move.l   myraster,a1
         move.l   GrafBase,a6
         SYS      SetAPen(a6)
         move.l   d3,d0
         move.l   d4,d1

         lsr.w    #6,d0
         lsr.w    #6,d1
         and.l    #$ffff,d0
         and.l    #$ffff,d1

         SYS      WritePixel(a6)

         rts


pset:

         move.l   d0,d3
         move.l   d1,d4
         move.b   #1,d0                   ; 1 = white
         move.l   GrafBase,a6
         move.l   myraster,a1
         SYS      SetAPen(a6)
         move.l   d3,d0
         move.l   d4,d1

         lsr.l    #6,d0
         lsr.l    #6,d1
         and.l    #$ffff,d0
         and.l    #$ffff,d1

         SYS      WritePixel(a6)

         rts



point_maker:

         jsr      rando                   ; x values
         move.w   d0,d2
         and.w    #x_and,d0
         add.w    #xlower,d0
         move.w   d0,xold_st(a3)

         jsr      rando                   ; y values
         and.w    #y_and,d0
         add.w    #ylower,d0
         cmp.w    #y_rang,d0
         bls      rep_y
         asr.w    #1,d0

rep_y:
         move.w   d0,yold_st(a3)

         and.b    #3,d2                   ; side distance factor
         add.b    #1,d2
         move.b   d2,dx_st(a3)
         rts



* Random number generator with d0 returning the number (others saved)

randomize:
         move.w   #91,d0                  ; the seed
         move.w   d0,rndsav
         move.b   #91,d0
         move.b   d0,rndlow
         rts

rando:
         move.l   a0,-(sp)
         move.l   d1,-(sp)

         lea      rndsav,a0
         move.w   #$4321,d0
         mulu     (a0),d0
         add.l    #1,d0
         move.w   d0,(a0)
         move.b   (a0),d1
         eor.b    d0,d1
         move.b   d1,rndlow

         move.l   (sp)+,d1
         move.l   (sp)+,a0
         rts



* get message to see if user closed the window

getmsg:
         movea.l   _AbsExecBase,a6
         movea.l   newwindowptr,a0
         movea.l   wd_UserPort(a0),a0
         SYS      GetMsg(a6)
         rts



* reply to the current message

replymsg:
         movea.l   d0,a1
         movea.l   _AbsExecBase,a6
         SYS      ReplyMsg(a6)
         rts



* Wait for user to close the window

waitforbutton:
         move.l   _AbsExecBase,a6
         move.l   newwindowptr,a0
         move.l   wd_UserPort(a0),a1
         move.l   #0,d3
         move.b   MP_SIGBIT(a1),d3
         move.l   #1,d0
         asl.l    d3,d0
         SYS      Wait(a6)

         rts


* Close a window

closeall:
         move.l   IntBase,a6
         move.l   newwindowptr,a0
         SYS      CloseWindow(a6)


* Close a screen

         move.l   IntBase,a6
         move.l   newscreenptr,a0
         SYS      CloseScreen(a6)


* Close the graphics library

         move.l      GrafBase,a1
         move.l      _AbsExecBase,a6
         SYS         CloseLibrary(a6)


*  Close the intuition library

         move.l   IntBase,a1
         move.l   _AbsExecBase,a6
         SYS      CloseLibrary(a6)

         rts


openerr:
         moveq    #-1,d1                  ; return code=bad
         move.l   d1,d0
         bra      exitprog



* Data section.  I prefer zeroing these things out when practical in the
* style of Jake Commander.  I also found you avoid pitfalls by NOT using
* SECTION directives needlessly.  With small code, you only ask for trouble.

savesp         dc.l  0

IntBase        dc.l  0          ; base addr. for intuit. calls
GrafBase       dc.l  0          ; base addr. for graphics calls

myraster       dc.l  0          ; pointer to new screen raster
myview         dc.l  0          ; pointer to new screen viewport

newwindowptr   dc.l  0          ; pointer to new window
newscreenptr   dc.l  0          ; pointer to new screen


windowvars
               dc.w  0                    ; nw_LeftEdge
               dc.w  0                    ; nw_TopEdge
               dc.w  320                  ; nw_Width
               dc.w  200                  ; nw_Height
               dc.b  0                    ; nw_DetailPen
               dc.b  1                    ; nw_BlockPen
               dc.l  IDCMP_FLAGS          ; nw_IDCMPFlags
               dc.l  ANDREWSGADGETS       ; nw_FLAGS
               dc.l  0                    ; nw_FirstGadget
               dc.l  0                    ; nw_CheckMark
               dc.l  andrews_window       ; nw_Title
               dc.l  0                    ; nw_Screen
               dc.l  0                    ; nw_BitMap
               dc.w  0                    ; nw_Minwidth
               dc.w  0                    ; nw_MinHeight
               dc.w  320                  ; nw_MaxWidth
               dc.w  200                  ; nw_MaxHeight
               dc.w  WBENCHSCREEN         ; nw_Type



screenvars
               dc.w  0                    ; ns_LeftEdge
               dc.w  0                    ; ns_TopEdge
               dc.w  320                  ; ns_Width
               dc.w  200                  ; ns_Height
               dc.w  3                    ; ns_Depth
               dc.b  3                    ; ns_DetailPen
               dc.b  1                    ; ns_BlockPen
               dc.w  0                    ; ns_ViewModes
               dc.w  WBENCHSCREEN         ; ns_Type
               dc.l  0                    ; ns_Font
               dc.l  andrews_screen       ; ns_DefaultTitle
               dc.l  0                    ; ns_Gadgets
               dc.l  0                    ; ns_CustomBitMap

*  Library definitions

IntLibArgs     dc.b    'intuition.library',0

GrafLibArgs    dc.b     'graphics.library',0


*  Andrew's Title definitions

andrews_window    dc.b   '3D Stars V 1.1',0

andrews_screen    dc.b   'Andrew',39,'s Screen',0

numb           equ   $40
lenth          equ   $10

xnew_st        equ   0
ynew_st        equ   2
dx_st          equ   4
dy_st          equ   6
xold_st        equ   8
yold_st        equ   $a
viaddr         equ   $c
vidata         equ   $e

x_and          equ   254*$40
x_rang         equ   318*64
zero           equ   0
y_and          equ   254*$40
y_rang         equ   197*64

xlower         equ   3*$40
ylower         equ   11*$40

ANDREWSGADGETS     equ  ACTIVATE!WINDOWCLOSE!BACKDROP
IDCMP_FLAGS        equ  CLOSEWINDOW!RAWKEY



rndsav         ds.w  2
rndlow         ds.b  4


* star variables

speed          ds.b  2

pont           ds.b  numb*lenth   ;intended to be an array of 1024 bytes

pontend        ds.b  1            ;allocate one byte. Name its spot pontend

x_centre       ds.w  1
y_centre       ds.w  1
x_abs          ds.w  1
y_abs          ds.w  1



      END      ; Boy, these assembler types have no flair.  How 'bout:

                   ; Th- Th- Th- Th-  That's All Folks!!          -TJE
