* 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.
*
* Note:  This playroutine was not originally written by me.  In general
* these playroutines are public domain, so I am bringing the versions
* modified for MultiPlayer under the General Public License.  In the
* few cases of already-copyrighted playroutines, the above copyright
* notice applies only to the parts of the file written by me.
*
* $Id: oktaplay.asm,v 4.1 92/06/21 11:14:42 BAF Exp Locker: BAF $
*

        include "player.i"
        include "bry/macros.i"

        code    text

        xref    modmem,modend,intsongpos,intrepeat,diecorrupt,dmawait,getfreqmodspeed
        xref    okta8start

        xdef    oktastart

oktastart:
        bsr.b   2$
        lea     rs_channelmodes(pc),a0
        tst.l   (a0)+
        bne     okta8start
        tst.l   (a0)+
        bne     okta8start

        plstartret 9$

1$      lea     name(pc),a0
        ml      a0,d0
        rts

2$      movem.l d2-d7/a2-a6,-(sp)
        jsr     rs_init(pc)
        bmi     diecorrupt
        movem.l (sp)+,d2-d7/a2-a6
        rts

        cnop    0,4
        dc.l    gmod_Hook+4
9$      gmodnop
        gmodbra 2$                      ; StartMusic
        gmodnop
        gmodnop
        gmodnop
        gmodnop
        gmodnop
        gmodnop
        gmodbra aud0int
        gmodbra aud1int
        gmodbra aud2int
        gmodbra aud3int
        gmodnop
        gmodnop
        gmodnop
        gmodbra getfreqmodspeed         ; GetFrequency
        gmodbra rs_int                  ; TimerTick
        gmodbra 1$                      ; GetMakerName
        move.l  #GMODHF_REPEAT!GMODHF_SEQUENCE,d0       ; Hook
        rts


**********************************
* OKTALYZER V1.1 REPLAYER SOURCE *
**********************************

;by A.Sander with Defpac2
;(C) 1989 VERLAG MAYER
;- only for 4-Channels

* init ********************************

p:

rs_init         move.l  modmem,a5
                cmp.l   #'OKTA',(a5)+
                bne     rs_error2
                cmp.l   #'SONG',(a5)+
                bne     rs_error2
                move.l  a5,a0
                lea     rs_cmformat(pc),a1
                bsr     rs_search
*                lea     rs_channelmodes(pc),a0
*                tst.l   (a0)+
*                bne     rs_error2
*                tst.l   (a0)+
*                bne     rs_error2
                move.l  a5,a0
                lea     rs_extformat(pc),a1
                bsr     rs_search
                move.l  a5,a0
                bsr     rs_getpatts
                move.l  a5,a0
                bsr     rs_getsamples

                clr.w   rs_pointer
                bsr     rs_gettrkpos
                sub.l   #16,rs_trkpos
                subq.w  #1,rs_patty

                move.l  #$40404040,rs_vol
                clr.w   rs_filter
                move.w  rs_speed,rs_actspeed
                clr.w   rs_actcyc
                move.w  #-1,rs_nextpt

                lea     rs_pbuffs,a0
                moveq   #15,d0
rs_loop4        clr.l   (a0)+
                dbf     d0,rs_loop4
                lea     rs_pattline,a0
                moveq   #3,d0
rs_loop5        clr.l   (a0)+
                dbf     d0,rs_loop5

                cq      d0
                cq      d1
                mw      rs_len(pc),d1
                jsr     intsongpos

                moveq   #0,d0
                rts
rs_error2       moveq   #-1,d0
                rts

* format search ***********************

;a0 fpt
;a1 format list

rs_search       move.l  a0,a2
                move.l  (a1)+,d0
                beq.s   rs_ex
rs_loop         cmp.l   modend,a2
                bhs.s   rs_ex
                cmp.l   (a2)+,d0
                bne.s   rs_next
                move.l  (a1)+,d0
                cmp.l   (a2)+,d0
                ble.s   rs_nocorrect
                move.l  -4(a2),d0
rs_nocorrect    move.l  (a1)+,a3
rs_copy         subq.l  #1,d0
                bmi.s   rs_search
                move.b  (a2)+,(a3)+
                bra.s   rs_copy
rs_next         add.l   (a2)+,a2
                bra.s   rs_loop
rs_ex           rts

* pattern descriptor ******************

rs_getpatts     lea     rs_pattpts(pc),a1
                move.l  #'PBOD',d0
rs_loop2        cmp.l   modend,a0
                bhs.s   rs_ready
                movem.l (a0)+,d1-d2
                cmp.l   d0,d1
                beq.s   rs_got
                add.l   d2,a0
                bra.s   rs_loop2
rs_got          move.l  a0,(a1)+
                add.l   d2,a0
                bra.s   rs_loop2
rs_ready        rts

* sample descriptor *******************

rs_getsamples   lea     rs_samplepts(pc),a1
                lea     rs_samples(pc),a2
                move.l  #'SBOD',d0
rs_loop2a       cmp.l   modend,a0
                bhs.s   rs_sready
                movem.l (a0)+,d1-d2
                cmp.l   d0,d1
                beq.s   rs_gots
                add.l   d2,a0
                bra.s   rs_loop2a
rs_gots         tst.l   20(a2)
                bne.s   rs_setsample
                lea     32(a2),a2
                clr.l   (a1)+
                bra.s   rs_gots
rs_setsample    move.l  a0,(a1)+
                lea     32(a2),a2
                add.l   d2,a0
                bra.s   rs_loop2a
rs_sready       rts

* exit ********************************

rs_int          movem.l d0-d7/a0-a6,-(sp)
                bsr.b   rs_rh
                movem.l (sp)+,d0-d7/a0-a6
                rts

rs_rh           bsr     rs_p4
                addq.w  #1,rs_actcyc
                move.w  rs_actspeed,d0
                cmp.w   rs_actcyc,d0
                ble.s   rs_addcyc
                rts

rs_addcyc       clr.w   rs_actcyc
                moveq   #16,d0
                add.l   d0,rs_trkpos
                addq.w  #1,rs_patty
                bsr     rs_getppatt
                tst.w   rs_nextpt
                bpl.s   rs_pattend
                cmp.w   rs_patty,d0
                bgt.s   rs_nonew
rs_pattend      clr.w   rs_patty
                tst.w   rs_nextpt
                bmi     rs_nonextpt
                move.w  rs_nextpt,rs_pointer
                bra.s   rs_newpos
rs_nonextpt     addq.w  #1,rs_pointer
rs_newpos       move.w  rs_pointer(pc),d0
                cmp.w   rs_len(pc),d0
                bne.s   rs_nonewinit
                clr.w   rs_pointer
                move.w  rs_speed(pc),rs_actspeed
                jsr     intrepeat
rs_nonewinit    mw      rs_pointer(pc),d0
                mw      rs_len(pc),d1
                jsr     intsongpos
                bsr     rs_gettrkpos
rs_nonew        move.l  rs_trkpos(pc),a0
                lea     rs_pattline(pc),a1
                move.l  (a0)+,(a1)+
                move.l  (a0)+,(a1)+
                move.l  (a0)+,(a1)+
                move.l  (a0)+,(a1)+
                move.w  #-1,rs_nextpt
                rts

rs_p4           tst.w   rs_actcyc
                bne.s   rs_effects

                bsr     rs_set
                tst.w   d4
                beq.s   rs_effects
                bsr     dmawait
                bsr     rs_setperiods
                or.w    #$8000,d4
                move.w  d4,$dff096
                bsr     dmawait
                bsr     rs_action

rs_effects      bsr     rs_effect
                lea     rs_vol,a0
                lea     $dff0a9,a1
                move.b  (a0)+,(a1)
                move.b  (a0)+,$10(a1)
                move.b  (a0)+,$20(a1)
                move.b  (a0)+,$30(a1)
                tst.b   rs_filter
                beq.s   rs_blink
                bclr    #1,$bfe001
                rts
rs_blink        bset    #1,$bfe001
                rts

rs_set          lea     rs_samplepts,a0
                lea     rs_pattline,a2
                lea     rs_pbuffs,a3
                lea     $dff0a0,a4
                lea     rs_periods,a6

                moveq   #0,d4
                moveq   #1,d5
                moveq   #3,d7

rs_ploop        bsr.s   rs_set4
                addq.w  #4,a2
                lea     16(a3),a3
                lea     $10(a4),a4
                add.w   d5,d5
                dbf     d7,rs_ploop
                rts

rs_set4         moveq   #0,d3
                move.b  (a2),d3
                beq     rs_noset
                subq.w  #1,d3
                moveq   #0,d0
                move.b  1(a2),d0
                add.w   d0,d0
                add.w   d0,d0
                move.l  0(a0,d0.w),d2
                beq     rs_noset
                lsl.w   #3,d0
                lea     rs_samples,a1
                add.w   d0,a1
                tst.w   30(a1)
                beq     rs_noset
                move.l  20(a1),d1
                lsr.l   #1,d1
                tst.w   d1
                beq     rs_noset
                move.w  #124,6(a4)
                lsl.w   #7,d5
                move.w  d5,$dff09a
                lsr.w   #7,d5
                move.w  d5,$dff096
                or.w    d5,d4
                move.l  d2,(a4)
                move.w  d3,12(a3)
                add.w   d3,d3
                move.w  0(a6,d3.w),14(a3)
                move.l  a0,-(sp)
                lea     rs_vol,a0
                moveq   #0,d0
                move.b  rs_volum1(pc,d7.w),d0
                move.b  29(a1),0(a0,d0.w)
                move.l  (sp)+,a0
                tst.w   26(a1)
                beq.s   rs_norep
                tst.w   24(a1)
                bne.s   rs_realrep

                move.w  26(a1),4(a4)
                clr.l   (a3)
                clr.w   4(a3)
                moveq   #0,d0
                move.w  26(a1),d0
                add.l   d0,d0
                add.l   d0,d2
                move.l  d2,6(a3)
                move.l  20(a1),d1
                sub.l   d0,d1
                lsr.l   #1,d1
                move.w  d1,10(a3)
                rts

rs_volum1       dc.b    3,2,1,0

rs_realrep      move.w  24(a1),4(a4)
                moveq   #0,d0
                move.w  24(a1),d0
                add.l   d0,d0
                add.l   d2,d0
                move.l  d0,(a3)
                move.w  26(a1),4(a3)
                moveq   #0,d0
                move.w  24(a1),d0
                add.w   26(a1),d0
                add.l   d0,d0
                add.l   d0,d2
                move.l  d2,6(a3)
                move.l  20(a1),d1
                sub.l   d0,d1
                lsr.l   #1,d1
                move.w  d1,10(a3)
                rts

rs_norep        move.w  d1,4(a4)
                moveq   #2,d0
                move.l  d0,(a3)
                move.w  #1,4(a3)
                clr.l   6(a3)
                clr.w   10(a3)
rs_noset        rts

rs_setperiods   lea     rs_pbuffs,a3
                lea     $dff000,a4
                btst    #0,d4
                beq.s   rs_notc1
                move.w  14(a3),$a6(a4)
rs_notc1        btst    #1,d4
                beq.s   rs_notc2
                move.w  14+16(a3),$b6(a4)
rs_notc2        btst    #2,d4
                beq.s   rs_notc3
                move.w  14+32(a3),$c6(a4)
rs_notc3        btst    #3,d4
                beq.s   rs_notc4
                move.w  14+48(a3),$d6(a4)
rs_notc4        rts

rs_action       lea     rs_pbuffs,a3
                lea     $dff0a0,a4
                moveq   #3,d7
rs_aloop        move.l  (a3),d0
                beq.s   rs_nopt
                move.l  d0,(a4)
                clr.l   (a3)
rs_nopt         move.w  4(a3),d0
                beq.s   rs_nolen
                move.w  d0,4(a4)
                clr.w   4(a3)
rs_nolen        lea     16(a3),a3
                lea     $10(a4),a4
                dbf     d7,rs_aloop
                rts

rs_effect       lea     p(pc),a1
                lea     rs_pattline,a2
                lea     rs_pbuffs,a3
                lea     $dff0a0,a4
                lea     rs_periods,a6
                moveq   #1,d5
                moveq   #3,d7
rs_eloop        bsr     rs_doeff
                addq.w  #4,a2
                lea     $10(a3),a3
                lea     $10(a4),a4
                add.w   d5,d5
                dbf     d7,rs_eloop
                rts

rs_doeff        moveq   #0,d0
                move.b  2(a2),d0
                add.w   d0,d0
                moveq   #0,d1
                move.b  3(a2),d1

                move.w  rs_effecttab(pc,d0.w),d0
                beq.s   rs_noeff
                bmi.s   rs_1eff

                jsr     0(a1,d0.w)
                bra.s   rs_noeff

rs_1eff         tst.w   rs_actcyc
                bne.s   rs_noeff
                neg.w   d0
                jsr     0(a1,d0.w)
rs_noeff        rts

rs_effecttab    dc.w    0,rs_portd-p,rs_portu-p,0,0,0
                dc.w    0,0,0,0,rs_arp-p,rs_arp2-p
                dc.w    0,rs_slided-p,0,p-rs_filt,0,p-rs_slideu
                dc.w    0,0,0,p-rs_slided,0,0
                dc.w    0,p-rs_posjmp,0,p-rs_release,p-rs_cspeed,0
                dc.w    rs_slideu-p,rs_volume-p,0,0,0,0

rs_portd        sub.w   d1,14(a3)
                bpl.s   rs_pdok
                move.w  #113,14(a3)
rs_pdok         move.w  14(a3),6(a4)
                rts

rs_portu        add.w   d1,14(a3)
                bpl.s   rs_puok
                move.w  #113,14(a3)
rs_puok         move.w  14(a3),6(a4)
                rts

rs_arp          move.w  12(a3),d2
                move.w  rs_actcyc,d0
                move.b  rs_divtab(pc,d0.w),d0
                bne.s   rs_val1
                and.w   #$f0,d1         ;runter
                lsr.w   #4,d1
                sub.w   d1,d2
                bra.s   rs_setarp

rs_val1         subq.b  #1,d0
                bne.s   rs_val2
                move.w  d2,8(a4)
                bra.s   rs_setarp

rs_val2         and.w   #$0f,d1
                add.w   d1,d2
                bra.s   rs_setarp

rs_divtab       dc.b    0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2

rs_arp2         move.w  12(a3),d2
                move.w  rs_actcyc,d0
                and.w   #3,d0
                bne.s   rs_val3
                bra.s   rs_setarp

rs_val3         subq.b  #1,d0
                bne.s   rs_val4
                and.w   #$f,d1
                add.w   d1,d2
                bra.s   rs_setarp

rs_val4         subq.b  #1,d0
                beq.s   rs_setarp
                and.w   #$f0,d1
                lsr.w   #4,d1
                sub.w   d1,d2

rs_setarp       tst.w   d2
                bpl.s   rs_arpok1
                moveq   #0,d2
rs_arpok1       cmp.w   #35,d2
                ble.s   rs_arpok2
                moveq   #35,d2
rs_arpok2       add.w   d2,d2
                move.w  0(a6,d2.w),d0
                move.w  d0,6(a4)
                move.w  d0,14(a3)
                rts

rs_slided       move.w  12(a3),d2
                sub.w   d1,d2
                move.w  d2,12(a3)
                bra.s   rs_setarp

rs_slideu       move.w  12(a3),d2
                add.w   d1,d2
                move.w  d2,12(a3)
                bra.s   rs_setarp

rs_cspeed       tst.b   d1
                beq.s   rs_nochange
                and.w   #$f,D1
                move.w  d1,rs_actspeed
rs_nochange     rts

rs_filt         tst.b   d1
                sne     rs_filter
                rts

rs_volume       move.l  a0,-(sp)
                lea     rs_vol,a0
                moveq   #0,d0
                move.b  volum2(pc,d7.w),d0
                add.w   d0,a0
                cmp.w   #$40,d1
                bgt.s   rs_4567
                move.b  d1,(a0)
rs_vex          move.l  (sp)+,a0
                rts

volum2          dc.b    3,2,1,0

rs_4567         sub.b   #$40,d1
                cmp.b   #$10,d1
                blt.s   rs_4
                sub.b   #$10,d1
                cmp.b   #$10,d1
                blt.s   rs_5
                sub.b   #$10,d1
                cmp.b   #$10,d1
                blt.s   rs_6
                sub.b   #$10,d1
                cmp.b   #$10,d1
                blt.s   rs_7
                bra.s   rs_vex

rs_6            tst.w   rs_actcyc
                bne.s   rs_vex

rs_4            sub.b   d1,(a0)
                bpl.s   rs_vex
                clr.b   (a0)
                bra.s   rs_vex

rs_7            tst.w   rs_actcyc
                bne.s   rs_vex

rs_5            add.b   d1,(a0)
                cmp.b   #$40,(a0)
                ble.s   rs_vex
                move.b  #$40,(a0)
                bra.s   rs_vex

rs_release      tst.l   6(a3)
                beq.s   rs_rex
                tst.w   10(a3)
                beq.s   rs_rex
                move.w  d5,d0
                lsl.w   #7,d0
                move.w  d0,$dff09a
                move.l  6(a3),(a4)
                move.w  10(a3),4(a4)
                clr.l   6(a3)
                clr.w   10(a3)
                move.w  d0,$dff09c
                or.w    #$8000,d0
                move.w  d0,$dff09a
rs_rex          rts

rs_posjmp       move.w  d1,d0
                and.w   #$f,d0
                lsr.w   #4,d1
                mulu    #10,d1
                add.w   d1,d0
                cmp.w   rs_len,d0
                bge.s   rs_nojmp
                move.w  d0,rs_nextpt
                jsr     intrepeat
rs_nojmp        rts

aud0int         clr.l   $a0(a0)
                move.w  #1,$a4(a0)
                move.w  #$80,$9a(a0)
                rts

aud1int         clr.l   $b0(a0)
                move.w  #1,$b4(a0)
                move.w  #$100,$9a(a0)
                rts

aud2int         clr.l   $c0(a0)
                move.w  #1,$c4(a0)
                move.w  #$200,$9a(a0)
                rts

aud3int         clr.l   $d0(a0)
                move.w  #1,$d4(a0)
                move.w  #$400,$9a(a0)
                rts

rs_gettrkpos    lea     rs_patterns,a0
                add.w   rs_pointer,a0
                moveq   #0,d0
                move.b  (a0),d0
                bsr.s   rs_getpattern
                move.l  a0,rs_trkpos
                clr.w   rs_patty
                rts

rs_getppatt     lea     rs_patterns,a0
                add.w   rs_pointer,a0
                moveq   #0,d0
                move.b  (a0),d0
rs_getpattern   lea     rs_pattpts,a0
                add.w   d0,d0
                add.w   d0,d0
                move.l  0(a0,d0.w),a0
                move.w  (a0)+,d0
                rts

rs_cmformat     dc.l    'CMOD',8,rs_channelmodes
rs_extformat    dc.l    'SAMP',36*32,rs_samples
                dc.l    'SPEE',2,rs_speed
                dc.l    'PLEN',2,rs_len
                dc.l    'PATT',128,rs_patterns,0
rs_channelmodes ds.w    4
rs_samples      ds.b    36*32
rs_speed        dc.w    6
rs_len          dc.w    1
rs_patterns     ds.b    128
rs_pattpts      ds.l    64
rs_samplepts    ds.l    36
rs_patty        ds.w    1
rs_trkpos       ds.l    1
rs_pbuffs       ds.l    16
rs_pattline     ds.l    4
rs_actspeed     ds.w    1
rs_actcyc       ds.w    1
rs_nextpt       ds.w    1
rs_pointer      ds.w    1
rs_vol          ds.l    1
rs_filter       ds.w    1
rs_oldaud       ds.l    1
rs_periods      dc.w    $358,$328,$2FA,$2D0,$2A6,$280,$25C,$23A,$21A
                dc.w    $1FC,$1E0,$1C5,$1AC,$194,$17D,$168,$153,$140
                dc.w    $12E,$11D,$10D,$FE,$F0,$E2,$D6,$CA,$BE
                dc.w    $B4,$AA,$A0,$97,$8F,$87,$7F,$78,$71

name    dc.b    "Oktalyzer (4 channel)",0

        end
