* 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: flash.asm,v 3.1 92/05/25 07:51:22 BAF Exp $
*

        include "exec/types.i"
        include "exec/nodes.i"
        include "exec/tasks.i"
        include "exec/semaphores.i"
        include "exec/libraries.i"
        include "exec/funcdef.i"
        include "exec/exec_lib.i"
        include "graphics/gfx.i"
        include "graphics/rastport.i"
        include "graphics/gfx_lib.i"
        include "dos/dos.i"
        include "bry/macros.i"
        include "player.i"

FLASHYSTACKSIZE equ     1024

        xdef    _flashyupdate,@flashyupdate
        xdef    _flashytask,_flashysem
        xdef    _spectrum,_flashactive,scopechandata,_scopeinterval,_flashytaskptr
        xdef    notetab,scrollmod,scrolllines,scrollline


        xref    _LinkerDB,_SysBase,_GfxBase
        xref    _spectrumrastport,_spectrumboxleft,_spectrumboxtop
        xref    _scoperastport,_scopeboxlleft,_scopeboxrleft,_scopeboxtop
        xref    _qscoperastport,_qscopeboxlx,_qscopeboxrx,_qscopeboxty,_qscopeboxby
        xref    _noterastport,_noteboxleft,_noteboxtop
        xref    _flashactive,_spectrum

        code    text

*** _flashyupdate - Code executed in Flashy task
_flashyupdate
@flashyupdate
        lea     _LinkerDB,a4

\loop
        ml      _SysBase(a4),a6

        ml      #SIGBREAKF_CTRL_F,d0    ; Wait for an update signal
        jl      Wait

        lea     _flashysem,a0           ; Don't want to get killed while we're drawing
        jl      ObtainSemaphore

        ml      _GfxBase(a4),a6
        mq      #0,d7

        tst.l   _spectrumrastport
        bz.b    \nospectrum
        bsr     dospectrum
\nospectrum

        tst.l   _scoperastport          ; See if stereo scope is active
        bz      \noscope
        cq      d2

        lea     scopechandata(a4),a0    ; Left scope
        lea     scopechandata+scd_SIZEOF*3(a4),a1
        mw      _scopeboxlleft,d2
        bsr     doscope

        mw      _scopeboxrleft,d2       ; Right scope
        lea     scopechandata+scd_SIZEOF*1(a4),a0
        lea     scopechandata+scd_SIZEOF*2(a4),a1
        bsr     doscope
\noscope

        tst.l   _qscoperastport         ; See if quadrascope is active
        bz      \noqscope
        cq      d2
        cq      d3

        mw      _qscopeboxlx,d2         ; Channel 0 scope (top-left)
        mw      _qscopeboxty,d3
        lea     scopechandata(a4),a0
        bsr     doqscope

        mw      _qscopeboxrx,d2         ; Channel 1 scope (top-right)
        mw      _qscopeboxty,d3
        lea     scopechandata+scd_SIZEOF*1(a4),a0
        bsr     doqscope

        mw      _qscopeboxrx,d2         ; Channel 2 scope (bottom-right)
        mw      _qscopeboxby,d3
        lea     scopechandata+scd_SIZEOF*2(a4),a0
        bsr     doqscope

        mw      _qscopeboxlx,d2         ; Channel 3 scope (bottom-left)
        mw      _qscopeboxby,d3
        lea     scopechandata+scd_SIZEOF*3(a4),a0
        bsr     doqscope

\noqscope

        tst.l   _noterastport           ; Draw the note scroller
        bz.b    \nonote
        bsr     donote
\nonote

        and.b   d7,_flashactive(a4)

        lea     _flashysem,a0           ; Don't want to get killed while we're drawing
        ml      _SysBase(a4),a6
        jl      ReleaseSemaphore

        bra     \loop                   ; Infinite loop

*** dospectrum - Draw the spectrum display
dospectrum
        lea     specplane0,a0
        lea     specplane1,a1
        mq      #SPECTRUMHEIGHT-1,d0
        mq      #0,d2
        mq      #$7f,d3
        mq      #$fffffffe,d4
\plotspecline
        lea     _spectrum(a4),a2
        mq      #SPECTRUMRES-1,d1
\plotspecbyte
        cmp.b   (a2)+,d0
        blo.b   \plotspecbar
        mb      d2,(a0)+
        mb      d2,(a1)+
        dbra    d1,\plotspecbyte
        dbra    d0,\plotspecline
        bra.b   \plotspecout
\plotspecbar
        mb      d3,(a0)+
        mb      d4,(a1)+
        dbra    d1,\plotspecbyte
        dbra    d0,\plotspecline
\plotspecout

        lea     spectrumbitmap,a0       ; Copy the new display
        cq      d0
        cq      d1
        ml      _spectrumrastport,a1
        mb      #3,rp_Mask(a1)
        cq      d2
        mw      _spectrumboxleft,d2
        cq      d3
        mw      _spectrumboxtop,d3
        mq      #SPECTRUMWIDTH-1,d4
        addq.w  #1,d4
        mq      #SPECTRUMHEIGHT,d5
        mw      #$0c0,d6
        jl      BltBitMapRastPort

        mq      #0,d1
        lea     _spectrum(a4),a0
        mq      #SPECTRUMRES-1,d0
\decspec
        tst.b   (a0)+
        bz.b    \decspecz
        mq      #-1,d7
        subq.b  #3,-1(a0)
        bpl.b   \decspecz
        clr.b   -1(a0)
\decspecz
        dbra    d0,\decspec
        rts

*** doscope - Draw one display in the stereo scope
doscope
        cq      d0

        tst.w   scd_len(a0)             ; First channel in use?
        bz.b    \noch0
        mw      scd_pos(a0),d0          ; Find first channel's data
        ml      scd_sample(a0),a0
        add.l   d0,a0
        mq      #-1,d7                  ; Flag that there's something to display
        bra.b   \hasch0
\noch0
        lea     zeros,a0
\hasch0

        tst.w   scd_len(a1)             ; Second channel in use?
        bz.b    \noch1
        mw      scd_pos(a1),d0
        ml      scd_sample(a1),a1
        add.l   d0,a1
        mq      #-1,d7                  ; Flag that there's something to display
        bra.b   \hasch1
\noch1
        lea     zeros,a1
\hasch1

\startscan
        lea     scopeplane,a3           ; Clear the bitplane first
        mq      #(SCOPEWIDTH/8*SCOPEHEIGHT)/16-1,d0
        cq      d1
\clear
        ml      d1,(a3)+
        ml      d1,(a3)+
        ml      d1,(a3)+
        ml      d1,(a3)+
        dbra    d0,\clear

        mq      #SCOPEWIDTH/8-1,d0      ; Plot the scope
        lea     -SCOPEWIDTH/8*SCOPEHEIGHT/2(a3),a2
        mw      #$fff8,d5
\scopebyte
        mq      #8-1,d1
\scopebit
        mb      (a0)+,d3
        ext.w   d3
        mb      (a1)+,d4
        ext.w   d4
        add.w   d4,d3
        asr.w   #1,d3
        and.w   d5,d3
        bset.b  d1,0(a2,d3.w)
        dbra    d1,\scopebit
        addq.w  #1,a2
        dbra    d0,\scopebyte

        lea     scopebitmap,a0          ; Copy the new scope display
        cq      d0
        cq      d1
        ml      _scoperastport,a1
        mb      #1,rp_Mask(a1)
        cq      d3
        mw      _scopeboxtop,d3
        mq      #SCOPEWIDTH,d4
        mq      #SCOPEHEIGHT,d5
        mw      #$0c0,d6
        jl      BltBitMapRastPort

        rts

*** doqscope - Draw one display in the quadrascope
doqscope
        cq      d0

        tst.w   scd_len(a0)             ; First channel in use?
        bz.b    \noch0
        mw      scd_pos(a0),d0          ; Find first channel's data
        ml      scd_sample(a0),a0
        add.l   d0,a0
        mq      #-1,d7                  ; Flag that there's something to display
        bra.b   \hasch0
\noch0
        lea     zeros,a0
\hasch0

\startscan
        lea     scopeplane,a3           ; Clear the bitplane first
        mq      #(SCOPEWIDTH/8*SCOPEHEIGHT)/16-1,d0
        cq      d1
\clear
        ml      d1,(a3)+
        ml      d1,(a3)+
        ml      d1,(a3)+
        ml      d1,(a3)+
        dbra    d0,\clear

        mq      #SCOPEWIDTH/8-1,d0      ; Plot the scope
        lea     -SCOPEWIDTH/8*SCOPEHEIGHT/2(a3),a2
        mw      #$fff8,d5
\scopebyte
        mq      #8-1,d1
\scopebit
        mb      (a0)+,d4
        ext.w   d4
        and.w   d5,d4
        bset.b  d1,0(a2,d4.w)
        dbra    d1,\scopebit
        addq.w  #1,a2
        dbra    d0,\scopebyte

        lea     scopebitmap,a0          ; Copy the new scope display
        cq      d0
        cq      d1
        ml      _qscoperastport,a1
        mb      #1,rp_Mask(a1)
        mq      #SCOPEWIDTH,d4
        mq      #SCOPEHEIGHT,d5
        mw      #$0c0,d6
        jmp     _LVOBltBitMapRastPort(a6)

*** donote - Draw the note scroller

dolong  macro
        tst.w   (a0)+
        sne.b   d0
        mw      (a0)+,d7
        and.w   d6,d7
        sne.b   d7
        and.b   d5,d7
        mb      d7,(a1)+
        mb      d0,(a1)+
        mb      d0,(a1)+
        mb      d7,(a1)+
        endm

donote
        ml      notetab(a4),a0
        lea     noteplane,a1
        mw      scrollline(a4),d0
        mw      scrolllines(a4),d1
        cmp.w   d1,d0
        blo.b   \lineok
        cq      d0
\lineok
        cmp.w   oldscrollline(a4),d0
        beq.b   \sameline
        mw      d0,oldscrollline(a4)

        mq      #16,d4
        mw      #NOTEHEIGHT/2-1,d2
        sub.w   #NOTEHEIGHT/4,d0
        bmi.b   \topblank
        beq.b   \topexact

\topchopped                             ; Top part of note table is chopped off
        mw      scrollmod(a4),d3
        add.w   d4,d3
\topchoploop
        add.w   d3,a0
        subq.w  #1,d1
        subq.w  #1,d0
        bnz.b   \topchoploop
        bra.b   \topexact

\sameline
        cq      d2
        mw      _noteboxleft,d2
        cq      d3
        mw      _noteboxtop,d3
        cq      d4
        bra     \drawcenter

\topblank
        cq      d3                      ; Top part of box is blank
\topblankloop
        ml      d3,(a1)+
        ml      d3,(a1)+
        ml      d3,(a1)+
        ml      d3,(a1)+
        add.w   d4,a1
        subq.w  #1,d2
        addq.w  #1,d0
        bnz.b   \topblankloop

\topexact
        mq      #$55,d5
        mw      #$fff,d6
\loop                                   ; Copy the note table straight to the display
        subq.w  #1,d1
        bmi.b   \botblank
        dolong
        dolong
        dolong
        dolong
        add.w   d4,a1
        add.w   scrollmod(a4),a0
        dbra    d2,\loop
        bra.b   \blit

\botblank                               ; Exhausted the note table, still more display
        cq      d3
\botblankloop
        ml      d3,(a1)+
        ml      d3,(a1)+
        ml      d3,(a1)+
        ml      d3,(a1)+
        add.w   d4,a1
        dbra    d2,\botblank

\blit
        mq      #-1,d7

        lea     notebitmap,a0           ; Copy the new scope display
        cq      d0
        cq      d1
        ml      _noterastport,a1
        mb      #1,rp_Mask(a1)
        cq      d2
        mw      _noteboxleft,d2
        cq      d3
        mw      _noteboxtop,d3
        cq      d4
        mw      #NOTEWIDTH,d4
        mq      #NOTEHEIGHT,d5
        mw      #$0c0,d6
        jl      BltBitMapRastPort

\drawcenter
        ml      _noterastport,a1        ; Draw the center line
        mb      #2,rp_Mask(a1)
        ml      d2,d0
        ml      d3,d1
        add.w   #NOTEHEIGHT/2-1,d1
        add.w   #NOTEWIDTH-1,d2
        add.w   #NOTEHEIGHT/2+1,d3
        jmp     _LVORectFill(a6)

        bss     __MERGED

_scopeinterval  ds.l    1               ; Audio intervals per flash frame

_flashytaskptr  ds.l    1               ; Pointer to _flashytask if active

scopechandata   ds.b    scd_SIZEOF*4    ; Scope channel data

notetab         ds.l    1               ; Stuff for note scroller
scrollmod       ds.w    1
scrolllines     ds.w    1
scrollline      ds.w    1
oldscrollline   ds.w    1

_flashactive    ds.b    1               ; Flashy window is clear and inactive

                ds.b    1               ; Padding on left
                even
_spectrum       ds.b    SPECTRUMRES     ; Spectrum of volumes
                ds.b    1               ; Padding on right

        data    data

_flashytask     dc.l    0,0
                dc.b    NT_TASK,-5
                dc.l    flashyname
                ds.b    TC_SPREG-TC_FLAGS
                dc.l    0
                dc.l    stacklower
                dc.l    stackupper
                dc.l    0,0
                dc.l    _flashytask+TC_MEMENTRY+LH_TAIL
                dc.l    0
                dc.l    _flashytask+TC_MEMENTRY+LH_HEAD
                ds.b    TC_SIZE-(TC_MEMENTRY+12)

spectrumbitmap  dc.w    SPECTRUMWIDTH/8
                dc.w    SPECTRUMHEIGHT
                dc.b    0
                dc.b    2
                dc.w    0
                dc.l    specplane0,specplane1

scopebitmap     dc.w    SCOPEWIDTH/8
                dc.w    SCOPEHEIGHT
                dc.b    0
                dc.b    1
                dc.w    0
                dc.l    scopeplane

notebitmap      dc.w    NOTEWIDTH/8
                dc.w    NOTEHEIGHT
                dc.b    0
                dc.b    1
                dc.w    0
                dc.l    noteplane

flashyname      dc.b    "MultiPlayer Flashy Windows",0

        bss     udata

stacklower
                ds.b    FLASHYSTACKSIZE
stackupper

_flashysem      ds.b    SS_SIZE         ; Semaphore for starting/stopping flashytask

zeros           ds.b    SCOPEWIDTH

        bss     chip,chip

specplane0      ds.b    SPECTRUMWIDTH/8*SPECTRUMHEIGHT
scopeplane      ds.b    SCOPEWIDTH/8*SCOPEHEIGHT
noteplane       ds.b    NOTEWIDTH/8*NOTEHEIGHT
specplane1      ds.b    SPECTRUMWIDTH/8*SPECTRUMHEIGHT

        end
