* MultiPlayer
* Copyright (C) 1992 Bryan Ford
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* I (the author of MultiPlayer) can be contacted on the Internet at
* "bryan.ford@m.cc.utah.edu".  See "Player.doc" for other addresses.
*
* $Id: rexx.asm,v 5.1 92/09/14 18:39:35 BAF Exp $
*

        include "exec/types.i"
        include "exec/funcdef.i"
        include "exec/exec_lib.i"
        include "dos/dos.i"
        include "rexx/storage.i"
        include "rexx/rxslib.i"
        include "bry/macros.i"
        include "bry/remind.i"
        include "player.i"

rxcmd   macro   ; name,len
        dc.l    \1text
        dc.w    rexx\1-5$
        dc.w    \2
        endm

        xref    _remind_rem
        xref    _addcalls,loadmod,playmod,startmod,stopmod,endmod,contmod
        xref    _SysBase,_sysflags,_procpt,nocontinue
        xref    _windowopen,_windowclose

        xdef    _initrexx

        code    text

*** quotok - Call ARexx's StcToken, but "lose" any quotes around the string
* a0 = string
* a6 = rxbase
* Returns: Same as _LVOStcToken, except CCR = D1
quotok:
        jsr     _LVOStcToken(a6)

        tst.l   d1                      ; Check for a zero string
        beq.s   9$

        cmp.b   (a1),d0                 ; Check for initial quote
        bne.s   5$
        addq.l  #1,a1
        subq.l  #1,d1
        beq.s   9$
5$
        cmp.b   -1(a1,d1.l),d0          ; Check for ending quote
        bne.s   9$
        subq.l  #1,d1

9$      rts

*** argquotok - Calls quotok, but converts the token into an Argstring
* a0 = string
* a6 = rxbase
* d7 = checkrexx's return SP
* Returns: a0 = argstring, a1 = scan
* NOTE: Returns through the stack if out of memory
argquotok:
        bsr     freearg                 ; Free up a rxarg slot

        bsr     quotok                  ; Get the next token

        move.l  a0,-(sp)                ; Create the Argstring
        move.l  a1,a0
        move.l  d1,d0
        jsr     _LVOCreateArgstring(a6)
        move.l  a0,rxarg(a4)
        beq.s   99$

        move.l  (sp)+,a1
        rts

99$     lea     nomem(a4),a0            ; Return an error directly
        move.l  a0,d0
        ; fall through...
*** rexxerr - Generate an ARexx error message
* d0 = Error message or NULL if OK
* d7 = checkrexx's return SP
rexxerr:
        move.l  d7,sp                   ; Return straight to checkrexx

        tst.l   d0                      ; Check the error
        beq.s   9$
        move.l  d0,rxerr(a4)
        moveq   #10,d0

9$      rts

*** _initrexx - Initialize the ARexx message port and system
_initrexx:
        move.l  a6,-(sp)

        lea     endnode(a4),a0          ; Add the callnodes
        lea     endrexx(pc),a1
        move.l  a1,rn_callfunc(a0)
        move.l  a0,-(sp)
        clr.l   -(sp)
        clr.l   -(sp)
        lea     checknode(a4),a0
        lea     checkrexx(pc),a1
        move.l  a1,rn_callfunc(a0)
        move.l  a0,-(sp)
        jsr     _addcalls
        lea     4*4(sp),sp

        move.l  _SysBase(a4),a6         ; Open rexxsyslib
        lea     rxname(a4),a1
        moveq   #0,d0
        jsr     _LVOOpenLibrary(a6)
        move.l  d0,rxbase(a4)
        beq     9$

        lea     rxport(a4),a1           ; Add MsgPort to system list
        move.l  _procpt(a4),MP_SIGTASK(a1)
        jsr     _LVOAddPort(a6)

9$      move.l  (sp)+,a6
        rts

*** freearg - Free any currently allocated rxarg
* Returns: a0 = preserved
freearg:
        move.l  rxarg(a4),d0
        beq.s   9$
        movem.l a0/a6,-(sp)
        move.l  d0,a0
        move.l  rxbase(a4),a6
        jsr     _LVODeleteArgstring(a6)
        movem.l (sp)+,a0/a6
        clr.l   rxarg(a4)
9$      rts

*** endrexx - Close the ARexx port and free everything
* Returns: d0 = Overlay handle to unlock
endrexx:
        tst.l   rxbase(a4)              ; See if we ever opened successfully
        bz      9$

        bsr     freearg                 ; Free any curently allocated rxarg

        move.l  a6,-(sp)

        move.l  _SysBase(a4),a6
        jsr     _LVOForbid(a6)

1$      lea     rxport(a4),a0           ; Get rid of all dead messages
        jsr     _LVOGetMsg(a6)
        tst.l   d0
        beq.s   19$
        move.l  d0,a1
        moveq   #20,d0
        move.l  d0,rm_Result1(a1)
        clr.l   rm_Result2(a1)
        jsr     _LVOReplyMsg(a6)
        bra.s   1$
19$
        lea     rxport(a4),a1           ; Remove the message port
        jsr     _LVORemPort(a6)

        jsr     _LVOPermit(a6)

        move.l  rxbase(a4),a1           ; Close the library
        clr.l   rxbase(a4)
        jsr     _LVOCloseLibrary(a6)

        move.l  (sp)+,a6

9$      pea     checknode(a4)           ; Remove the callnodes
        jsr     _remind_rem
        pea     endnode(a4)
        jsr     _remind_rem
        addq    #8,sp

        rts

*** rexxload - Load a module without playing it
rexxload:
        bsr     quotok                  ; Find the filename

        move.l  a1,a0                   ; Load the module
        bsr     loadmod

        bra     rexxerr

*** rexxplay - Play a loaded or not-yet-loaded module
rexxplay:
        bsr     argquotok               ; Find the filename or song number
        tst.l   d1
        beq.s   5$

        movem.l a0/a1,-(sp)             ; See if it's a number
        jsr     _LVOCVa2i(a6)
        tst.l   d1
        bne.s   5$

        move.l  (sp)+,a0                ; Load the file
        bsr     loadmod
        tst.l   d0
        bne     rexxerr

        move.l  (sp)+,a0                ; Find second token
        bsr     argquotok

        jsr     _LVOCVa2i(a6)           ; Maybe *this* one's a number

5$      ;move.l d1,d0                   ; Start playing the module
        bsr     playmod

        bra     rexxerr

*** rexxstop - Stop a currently playing module
rexxstop:
        bra     stopmod

*** rexxeject, rexxunload - Unload any module in memory
rexxeject:
rexxunload:
        bra     endmod

*** rexxcontinue - Continue module, called from rexx.a
rexxcontinue:
        bsr     contmod                 ; Try to continue the module

        tst.l   d0                      ; See if it was successful
        beq     rexxerr
        move.l  d0,rxerr(a4)

        lea     nocontinue(a4),a0       ; See if it couldn't continue
        cmp.l   a0,d0
        bne     rexxerr

        moveq   #5,d0                   ; Special error - returncode 5
        rts

*** rexxlasterror - Return the last error message in rm_Result2
rexxlasterror:
        move.l  rxerr(a4),a0            ; Create an Argstring for the error
        jsr     _LVOStrlen(a6)
        jsr     _LVOCreateArgstring(a6)
        beq.s   9$
        move.l  d0,rm_Result2(a2)

        moveq   #0,d0
        move.l  (sp)+,a0                ; Return to after the clr instruction
        addq.l  #4,a0
        jmp     (a0)

9$      moveq   #20,d0                  ; Big trouble!
        rts

*** rexxquit - Quit MultiPlayer
rexxquit:
        bset    #SB_KILL,_sysflags(a4)
        rts

*** rexxopenwin - Open the MultiPlayer window
rexxopenwin:
        pea     rexxerr(pc)
        jmp     _windowopen

*** rexxclosewin - Close the MultiPlayer window
rexxclosewin:
        jsr     _windowclose
        moveq   #0,d0
        rts

*** chexkrexx - Check for incoming ARexx messages
* Returns null
checkrexx:
        tst.l   rxbase(a4)              ; See if we ever opened successfully
        beq     99$

        movem.l d2-d5/d7/a2-a3/a6,-(sp)

1$      lea     rxport(a4),a0           ; Find the next message (a2)
        move.l  _SysBase(a4),a6
        jsr     _LVOGetMsg(a6)
        tst.l   d0
        bz.s    9$
        move.l  d0,a2

        move.l  rxbase(a4),a6           ; Find the command name
        move.l  rm_Args(a2),a0
        bsr     quotok
        move.l  a1,d2
        move.l  d1,d3
        move.l  a0,d4

        lea     59$(pc),a3              ; Search through command table
2$      move.l  (a3)+,d0
        beq.s   81$
        move.w  (a3)+,d5
        cmp.w   (a3)+,d3
        bne.s   2$
        move.l  d0,a0
        move.l  d2,a1
        move.l  d3,d0
        jsr     _LVOStrcmpN(a6)
        bne.s   2$

        move.l  sp,d7                   ; Place to return to on errors
        subq.l  #4,d7

        move.l  d4,a0                   ; Call the appropriate routine
5$      jsr     -2(pc,d5.w)

6$      clr.l   rm_Result2(a2)          ; Set the returncodes
        move.l  d0,rm_Result1(a2)       ; NOTE: First clr skipped by rexxlasterror!

        move.l  _SysBase(a4),a6         ; Return the message
        move.l  a2,a1
        jsr     _LVOReplyMsg(a6)

        bra     1$                      ; Back for more

9$      movem.l (sp)+,d2-d5/d7/a2-a3/a6
99$     cq      d0
        rts

81$     moveq   #10,d0
        bra     6$

59$     rxcmd   load,4                  ; Command table
        rxcmd   play,4
        rxcmd   stop,4
        rxcmd   eject,5
        rxcmd   unload,6
        rxcmd   continue,8
        rxcmd   quit,4
        rxcmd   lasterror,9
        rxcmd   openwin,11
        rxcmd   closewin,12
        dc.l    0

        data    __MERGED

rxport  dc.l    0,0
        dc.b    NT_MSGPORT,0
        dc.l    rxportname
        dc.b    PA_SIGNAL,SIGBREAKB_CTRL_E
        dc.l    0
1$      dc.l    2$
2$      dc.l    0
        dc.l    1$

rxname          dc.b    "rexxsyslib.library",0
rxportname      dc.b    "RXTRACKER",0
nomem           dc.b    "Not enough memory",0

loadtext        dc.b    "LOAD"
playtext        dc.b    "PLAY"
stoptext        dc.b    "STOP"
ejecttext       dc.b    "EJECT"
unloadtext      dc.b    "UNLOAD"
continuetext    dc.b    "CONTINUE"
quittext        dc.b    "QUIT"
lasterrortext   dc.b    "LASTERROR"
openwintext     dc.b    "OPENWINDOWS"
closewintext    dc.b    "CLOSEWINDOWS"

        bss     __MERGED

rxbase          ds.l    1                       ; rexxsyslib base
rxerr           ds.l    1                       ; Last error message
rxarg           ds.l    1                       ; Currently allocated argstring

checknode       ds.b    rn_SIZEOF               ; CallNodes
endnode         ds.b    rn_SIZEOF

        end
