;*****************************************************************
;
;   Light Speed Player v1.20
;   Fastest Amiga MOD player ever :)
;   Written By Arnaud Carré (aka Leonard / OXYGENE)
;   Adapted to demo framework (and optimized) by platon42.
;   https://github.com/arnaud-carre/LSPlayer
;   twitter: @leonard_coder
;
;   "micro mode" player version ( average time: 1.5 scanline )
;   This mode focus on music data compression ratio. Suited for 4KiB or small intros
;   Do not support various BPM, music getPos/setPos and sample without a note
;
;   You can also use classic "standard" player to support all features
;   Or you can use generated "ultra fast" player code for half scanline replayer ("-insane" option)
;
;   LSP_MusicInitMicro      Initialize a LSP driver + relocate score&bank music data
;   LSP_MusicPlayTickMicro  Play a LSP music (call it per frame)
;
;*****************************************************************

;------------------------------------------------------------------
;
;   LSP_MusicInitMicro
;
;       In: a0: LSP music data(any memory)
;           a1: LSP sound bank(chip memory)
;
;------------------------------------------------------------------
;LSP_dataError:  illegal

LSP_MusicInitMicro:
        IF      0
        cmpi.l  #'LSPm',(a0)+   ; LSP "micro" mode signature
        bne.s   LSP_dataError
        cmpi.w  #$0118,(a0)+            ; this play routine supports v1.24 as minimal version of LPConvert.exe
        blt.s   LSP_dataError
        ELSE
        addq.l  #6,a0
        ENDC
        lea     fw_LspLastDmaCon(a6),a2
        clr.w   (a2)+ ; fw_LspLastDmaCon
        move.w  (a0)+,(a2)+             ; fw_LspCurrentBpm, default song BPM
        move.w  (a0)+,d7                ; instrument count
        move.l  a0,(a2)+                ; fw_LspInstruments, instrument tab addr
        move.l  a1,d1
        subq.w  #1,d7
.relocloop
        add.l   d1,(a0)
        addq.l  #6,a0
        add.l   d1,(a0)
        addq.l  #6,a0
        dbra    d7,.relocloop
        ;lea     fw_LspStreams(a6),a2
        lea     16*4(a0),a1
        ; do not stress about this rept, your exe packer will enjoy it
        REPT    16
        move.l  (a0)+,d1
        add.l   a1,d1
        move.l  d1,fw_LspLoopStreams-fw_LspStreams(a2)      ; set loopStreams at 0 by default
        move.l  d1,(a2)+
        ENDR
        bset.b  #1,$bfe001              ; disabling this fucking Low pass filter!!
        rts

;------------------------------------------------------------------
;
;   LSP_MusicPlayTickMicro
;
;       In: a5: should be $dff000
;       Out:None
;
;------------------------------------------------------------------
LSP_MusicPlayTickMicro:
        move.w  fw_LspLastDmaCon(a6),d0
        beq.s   .skip
        lea     fw_LspResetv(a6),a3
        lea     aud+4*ac_SIZEOF(a5),a2
        moveq.l #4-1,d7
.rloop  lea     -ac_SIZEOF(a2),a2
        btst    d7,d0
        beq.s   .norst
        move.l  (a3)+,ac_ptr(a2)
        move.w  (a3)+,ac_len(a2)
.norst  dbra    d7,.rloop

.skip   lea     fw_LspStreams(a6),a1
        moveq.l #0,d3
        lea     fw_LspResetv(a6),a3
        lea     aud+4*ac_SIZEOF(a5),a2
        moveq.l #4-1,d7
.vloop  lea     -ac_SIZEOF(a2),a2
        moveq.l #16,d4
        move.l  a1,a4
        move.l  (a4),a0
        move.b  (a0)+,d0        ; cmd for current voice
        move.l  a0,(a1)+        ; update cmd stream ptr
        adda.w  d4,a4
        add.b   d0,d0
        bcc.s   .novol
        move.l  (a4),a0
        move.b  (a0)+,ac_vol+1(a2)
        move.l  a0,(a4)
.novol  adda.w  d4,a4
        add.b   d0,d0
        bcc.s   .noper
        move.l  (a4),a0
        move.w  (a0)+,ac_per(a2)
        move.l  a0,(a4)
.noper  adda.w  d4,a4
        add.b   d0,d0
        bcc.s   .noinstr
        move.l  (a4),a0
        moveq.l #0,d1
        move.b  (a0)+,d1
        move.l  a0,(a4)

        ; prepare instrument
        IF  1
        mulu    #12,d1
        ELSE
        move.w  d1,d2
        lsl.w   #2,d1       ; x*4
        lsl.w   #3,d2       ; x*8
        add.w   d2,d1       ; x*(4+8)
        ENDIF
        move.l  fw_LspInstruments(a6),a0
        adda.w  d1,a0
        bset    d7,d3
        move.l  (a0)+,ac_ptr(a2)
        move.w  (a0)+,ac_len(a2)
        move.l  (a0)+,(a3)+
        move.w  (a0)+,(a3)+

.noinstr
        dbra    d7,.vloop

        move.w  d3,dmacon(a5)
        move.w  d3,fw_LspLastDmaCon(a6)
        move.l  fw_LspDmaConPatch(a6),a0
        move.b  d3,(a0)

        add.b   d0,d0
        bcc.s   .noloopcmd

        ; backup or restore current song position
        lea     fw_LspStreams(a6),a0
        lea     fw_LspLoopStreams(a6),a1
        add.b   d0,d0
        bcc.s   .skiprestore
        exg     a0,a1
.skiprestore
        ; do not stress about this rept, your exe packer will enjoy it
        REPT    16
        move.l  (a0)+,(a1)+
        ENDR
.noloopcmd
        rts
