 ;sound3 for Code Clinic page of Almanac
 ;Amiga Computing -March Issue
 ;M.Stanger Nov 91

                       ;adresses of routines used by C program
 XDEF  _soundtest
 XDEF  _bell
 XDEF  _sploit
 XDEF  _clearsound
 XDEF  _initsound
 XDEF  _playsig

      INCLUDE "EXEC/TYPES.I"
      INCLUDE "GRAPHICS/GFXBASE.I"
      INCLUDE "DEVICES/INPUTEVENT.I"
      INCLUDE "DEVICES/AUDIO.I"
      INCLUDE "DEVICES/TIMER.I"


 XREF  _AbsExecBase
                        ;Amiga library routines
 XREF  _LVOOpenDevice
 XREF  _LVOCloseDevice
 XREF  _LVOAllocSignal
 XREF  _LVOFindTask
 XREF  _LVOFreeSignal
 XREF  _LVODoIO
 XREF  _LVOSendIO
 XREF  _LVOWaitIO
 XREF  _LVOWaitPort
 XREF  _LVOGetMsg
 XREF  _LVOAddPort
 XREF  _LVORemPort
 XREF  _LVOReplyMsg
 XREF  _LVOAllocMem
 XREF  _LVORead
 XREF  _LVOOutput
 XREF  _LVOClose
 XREF  _LVOWrite
 XREF  _LVOOpenLibrary
 XREF  _LVOCloseLibrary
 XREF  _LVOOpen
 XREF  _LVODelay
 XREF  _LVOFreeMem
 XREF  _LVOExit

     CSECT text,code       ;this directive is used by the Lattice Assembler
                           ;this routine is the main program for the
_soundtest:                 ;assembler version
 jsr        _initsound     ;initialise the sound
 tst.l      errorflag      ;check for errors
 bne        nosound
hangabout:
  jsr       _playsig       ;read the joystick
  tst.l     xmove          ;make sound if horizontal move
  beq       nosploit
  jsr       _sploit
nosploit:        
  tst.l     ymove          ;make sound if vertical move
  beq       nobell
  jsr       _bell
nobell:
  tst.l     fire           ;exit if fire button pressed
  beq       hangabout
cleanup:    jsr _clearsound ;tidy up and exit
  rts


_playsig: 
 clr.l      d0               ;routine for reading  joystick 0
 clr.l      d1
 move.l     #0,xmove         ;clear previous values    
 move.l     #0,ymove
 move.l     #0,fire
 move.w     $dff00a,d0       ;move JOY0DAT to d0 (game port 0) 
 btst       #1,d0            ;test bit 1 for joystick right
 beq        left
 move.l     #1,xmove
left:
 btst       #9,d0            ;test bit 9 for joystick left
 beq        down
 move.l     #2,xmove
down:
 move.w     d0,d1            ;copy d0 to d1
 lsr.w      #1,d1            ;move bit 1 to bit 0, and bit 9 to bit 8
 eor.w      d0,d1            ;exclusive OR d0 and d1
 btst       #0,d1            ;test bit 0 for joystick down
 beq        up
 move.l     #4,ymove
up:
 btst       #8,d1            ;test bit 8 for joystick up
 beq        jfire
 move.l     #8,ymove
jfire:
 move.b     $bfe001,d1       ;CIA-A parallel port  A
 btst       #6,d1            ;test bit 6 for game port 0 fire button
 bne        skip
 move.l     #16,fire
skip:
 move.l     xmove,d0
 add.l      ymove,d0
 add.l      fire,d0
 rts

joystick2:
 move.w     $dff00c,d0       ;move JOY1DAT to d0 (game port 1)    
 btst       #1,d0            ;test bit 1 for joystick right
 beq        left2             
 move.l     #1,xmove
left2:
 btst       #9,d0            ;test bit 9 for joystick left
 beq        down2
 move.l     #2,xmove
down2:
 move.w     d0,d1            ;copy d0 to d1
 lsr.w      #1,d1            ;move bit 1 to bit 0,and bit 9 to bit 8
 eor.w      d0,d1            ;exclusive OR d0 and d1
 btst       #0,d1            ;test bit 0 for joystick down
 beq        up2
 move.l     #4,ymove
up2:
 btst       #$8,d1           ;test bit 8 for joystick up
 beq        jfire2
 move.l     #8,ymove
jfire2:
 move.b     $bfe001,d1       ;CIA-A parallel port A
 btst       #7,d1            ;test bit 7 for game port 1 fire button 
 bne        skip2
 move.l     #16,fire
skip2:
 move.l     xmove,d0
 add.l      ymove,d0
 add.l      fire,d0
 rts

_initsound:                  ;initialisation routine
 movem.l   d0-d7/a0-a6,-(sp)
 jsr       opendoslib        ;open dos library
 jsr       soundmemory       ;allocate memory for sound samples
 jsr       soundfiles        ;read in sound sample files
 jsr       sport             ;initialise audio device and sound ports
 movem.l   (sp)+,d0-d7/a0-a6
 rts
_clearsound:
 movem.l   d0-d7/a0-a6,-(sp)
 jsr       freememory        ;free allocated memory buffers
 jsr       cleansound        ;close down audio device
 jsr       closedoslib       ;close dos library
 movem.l   (sp)+,d0-d7/a0-a6
 rts


_bell:                       ;make the bell sound once
 movem.l   d0-d7/a0-a6,-(sp)
 tst.w     s0flag            ;check whether sound is in progress
 bne       bellout
 move.w    #1,s0flag
 move.l    _belldata,d7      ;sound data address
 add.l     #100,d7           ;allow for file header
 move.l    #(8186-100)/2,d6  ;length of data
 move.l    #428,d5           ;period
 move.l    #volume,d4        ;volume
 move.l    #1,d3             ;number of cycles
 lea       soundIOB0,a5      ;input/output structure
 lea       soundPort0,a1     ;sound port structure
 move.l    unit0,a0          ;channel 0
 bsr       setsound          ;set the sound going
bellout:
 movem.l   (sp)+,d0-d7/a0-a6
 rts

_sploit:                     ;makes the sploit sound once
 movem.l   d0-d7/a0-a6,-(sp)
 tst.w     s3flag            ;check whether sound is in progress
 bne       sploitout
 move.w    #1,s3flag
 move.l    _sploitdata,d7    ;sound data address
 add.l     #100,d7           ;allow for file header
 move.l    #(2250-100)/2,d6  ;data length
 move.l    #700,d5           ;period
 move.l    #volume,d4        ;volume
 move.l    #1,d3             ;number of cycles
 lea       soundPort3,a1     ;sound port structure
 lea       soundIOB3,a5      ;input/output structure
 move.l    unit3,a0          ;channel 3
 bsr       setsound          ;set the sound going
sploitout:
 movem.l   (sp)+,d0-d7/a0-a6
 rts

cleansound:                  ;close the audio device
 lea       allocIOB,a1
 jsr       _LVOCloseDevice(a6)
 lea       allocIOB,a5       ;clear the IO block
 move.b    #$FF,LN_TYPE(a5)
 move.l    #-1,IO_DEVICE(a5)
 move.l    #-1,IO_UNIT(a5)
 lea       allocPort,a5      ;free the signal bit
 move.b    MP_SIGBIT(a5),d0
 jsr       _LVOFreeSignal(a6)
 move.l    a5,a1
 jsr       _LVORemPort(a6)   ;remove the allocation port
 move.b    #$FF,LN_TYPE(a5)
 move.l    #-1,MP_MSGLIST(a5)
 rts

 ;open device and set up sound ports
 ;code adapted from CreatePort and CreateStdIO from ExecSupport

sport:                     
 move.l    _AbsExecBase,a6   
 move.l    #-1,d0
 jsr       _LVOAllocSignal(a6) ;allocate a signal bit
 cmp.l     #-1,d0
 beq       errorfound
 lea       allocPort,a5        ;set up allocation port
 move.l    #sound,LN_NAME(a5)
 move.b    #0,LN_PRI(a5)
 move.b    #0,MP_FLAGS(a5)     ;message port
 move.b    d0,MP_SIGBIT(a5)
 move.b    #4,LN_TYPE(a5)
 move.l    #0,a1               ;find current task
 jsr       _LVOFindTask(a6)
 movem.l   d0,MP_SIGTASK(a5)
 lea       allocPort,a1        ;add allocation port to list of ports
 jsr       _LVOAddPort(a6)
 lea       allocIOB,a5         ;set up IO structure
 move.b    #-40,LN_PRI(a5)
 lea       allocPort,a1
 move.l    a1,MN_REPLYPORT(a5)
 lea       allocationMap,a1
 move.l    a1,ioa_Data(a5)
 move.l    #1,ioa_Length(a5)
 lea       audioname,a0       ;open audio device
 lea       allocIOB,a1
 move.l    #0,d0
 move.l    #0,d1
 jsr       _LVOOpenDevice(a6)
 tst.l     d0
 bne       errorfound
 lea       allocIOB,a5
 move.l    IO_DEVICE(a5),a0
 movem.l   a0,device          ;save the device address
 lea       interrupt0,a5      ;link interrupt structure to the sound port
 lea       newbuffer0,a0
 move.l    a0,IS_CODE(a5)     
 lea       soundPort0,a5
 move.b    #1,MP_FLAGS(a5)
 move.b    #4,LN_TYPE(a5)
 lea       interrupt0,a0
 move.l    a0,MP_SIGTASK(a5)  ;initialise list header
 lea       MP_MSGLIST(a5),a0
 NEWLIST   a0
 lea       interrupt3,a5     ;link interrupt structure to its sound port
 lea       newbuffer3,a0
 move.l    a0,IS_CODE(a5)
 lea       soundPort3,a5
 move.b    #1,MP_FLAGS(a5)
 move.b    #4,LN_TYPE(a5)
 lea       interrupt3,a0
 move.l    a0,MP_SIGTASK(a5)
 lea       MP_MSGLIST(a5),a0 ;initialise list header
 NEWLIST   a0
 move.l    #0,errorflag
 rts

errorfound:                  ;set flag if necessary
 move.l   #1,errorflag
nosound:
 rts

setsound:                    ;put details in sound IO block
 move.l   _AbsExecBase,a6
 lea      allocIOB,a4        ;find allocation key
 move.w   ioa_AllocKey(a4),d0
 move.l   a1,MN_REPLYPORT(a5) ;sound port
 move.l   device,a1          ;device
 move.l   a1,IO_DEVICE(a5)
 move.l   a0,IO_UNIT(a5)     ;unit
 move.w   #CMD_WRITE,IO_COMMAND(a5) ;set the command
 move.b   #(ADIOF_PERVOL),IO_FLAGS(a5) ;command flags
 move.w   d0,ioa_AllocKey(a5) ;allocation key
 move.l   d7,ioa_Data(a5)    ;sound sample address
 move.l   d6,ioa_Length(a5)  ;data length
 move.w   d5,ioa_Period(a5)  ;period
 move.w   d4,ioa_Volume(a5)  ;volume
 move.w   d3,ioa_Cycles(a5)  ;number of cycles
 move.l   a5,a1
 BEGINIO                     ;start the sound
 rts

readfile:              ;reads in data file
 move.l   de,a6
 move.l   #1005,d2
 clr.l    d0
 jsr      _LVOOpen(a6)
 move.l   d0,d1
 beq      errorfound
 movem.l  d0,fe          ;filehandle
 move.l   d4,d2           ;buffer
 clr.l    d0
 move.l   d7,d3           ;length
 jsr      _LVORead(a6)
 move.l   d0,d1
 cmpi.l   #-1,d0
 clr.l    d0
 move.l   fe,d1
 jsr      _LVOClose(a6)
 clr.l    d0
  rts

opendoslib:                ;open dos library
 move.l   _AbsExecBase,a6
 move.l   #DN,a1
 clr.l    d0
 jsr      _LVOOpenLibrary(a6)
 tst.l    d0
 beq      errorfound
 movem.l  d0,de
 rts

closedoslib:              ;close dos library
 move.l   de,a1
 move.l   _AbsExecBase,a6
 jsr      _LVOCloseLibrary(a6)
 rts
abort1:
 rts

soundmemory:              ;allocate chip memory for sound samples
  move.l  _AbsExecBase,a6
  move.l  #8186,d0
  move.l  #65539,d1
  jsr     _LVOAllocMem(a6)
  tst.l   d0
  beq     errorfound
  movem.l d0,_belldata
  move.l  #2250,d0
  move.l  #65539,d1
  jsr     _LVOAllocMem(a6)
  tst.l   d0
  beq     errorfound
  movem.l d0,_sploitdata
  rts

freememory:               ;free sound sample memory
  move.l  _AbsExecBase,a6
  move.l  #8186,d0
  move.l  _belldata,a1
  jsr     _LVOFreeMem(a6)
  move.l  #2250,d0
  move.l  _sploitdata,a1
  jsr     _LVOFreeMem(a6)
  rts

soundfiles:               ;read in sound files
  move.l  _belldata,d4
  move.l  #8186,d7
  move.l  #_belladd,d1
  jsr     readfile
  move.l  _sploitdata,d4
  move.l  #2250,d7
  move.l  #_sploitadd,d1
  jsr     readfile
  rts

    ;this code is executed when the sound in channel 0 is finished
newbuffer0:               
 movem.l  d0-d7/a0-a6,-(sp)
 move.l   _AbsExecBase,a6
 lea      soundPort0,a0       ;get the message
 jsr      _LVOGetMsg(a6)
 clr.w    s0flag              ;clear the channel 0 flag
 movem.l (sp)+,d0-d7/a0-a6
 rts

   ;this code is executed when the sound in channel 3 is finished
newbuffer3:
 movem.l  d0-d7/a0-a6,-(sp)
 move.l   _AbsExecBase,a6
 lea      soundPort3,a0      ;get the message
 jsr      _LVOGetMsg(a6)
 clr.w    s3flag             ;clear the channel 3 flag
 movem.l  (sp)+,d0-d7/a0-a6
 rts

 SECTION  data,DATA
errorflag:     ;error flag for initialisation routines     
 dc.l    0        
volume:        ;sound level
 dc.l    64
fe:            ;filehandle
 ds.l    1
de:            ;dosbase
 ds.l    1
DN:
 dc.b    'dos.library',0
 ds.w    0
s0flag:        ;sound in progress flag for channel 0
 dc.w    0
s3flag:       ;sound in progress flag for channel 3
 dc.w    0
unit0:         ;channels
 dc.l    1
unit1:
 dc.l    2
unit2:
 dc.l    4
unit3:
 dc.l    8
sound:        ;name of allocation port
 dc.b    'sound',0
 ds.w    0
allocationMap: 
 dc.b    15
 ds.w    0
allocPort:    ;allocation port structure
 ds.b    MP_SIZE
allocIOB:     ;aloocation input/output block
 ds.b   ioa_SIZEOF
device:       ;device address
 ds.l   1
soundPort0:   ;soundport structure
 ds.b   MP_SIZE
soundPort3:
 ds.b   MP_SIZE
soundIOB0:    ;sound input/output structure  
 ds.b   ioa_SIZEOF
soundIOB3:
 ds.b   ioa_SIZEOF
audioname:    ;device name
 dc.b   'audio.device',0
 ds.w   0
_belldata:    ;memory buffers for sound data
 dc.l   0
_sploitdata:
 dc.l   0
_sploitadd:   ;filenames for sound sample fils
 dc.b   'sploit',0
 ds.w   0
_belladd:
 dc.b   'bell',0
 ds.w   0
interrupt0:   ;interrupt structures
 ds.b   IS_SIZE
 ds.w   0
interrupt3:
 ds.b   IS_SIZE
 ds.w   0
xmove:       ;variables used by playsig routine
 dc.l   0   
ymove:
 dc.l   0
fire:
 dc.l   0

 SECTION  mem,BSS
 END

