;*****************************************************************
;
;   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
;
;   "nano mode" player version (average time: 1-2 scanlines)
;   This mode focus on music data compression ratio. Suited for 4KiB or small intros
;   Only supports VBL timing, 32 KB max stream data, no portamentos/slides,
;   no support for 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_MusicInitNano      Initialize a LSP driver + relocate score&bank music data
;   LSP_MusicPlayTickNano  Play a LSP music (call it per frame)
;
;*****************************************************************

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

LSP_MusicInitNano:
        lea     fw_LspPeriodTable(a6),a2
        IF      0
        move.w  #$e2b3,d0
        move.l  #$0fc0fd20,d2
        moveq.l #0,d3
        moveq.l #36-1,d7
.ploop  mulu    #61865,d0
        swap    d0
        move.w  d0,d1
        lsr.w   #6,d1
        add.l   d2,d2
        subx.w  d3,d1
        move.w  d1,(a2)+
        dbra    d7,.ploop
        ELSE
        move.w  #$e2b3,d0
        moveq.l #36-1,d7
.ploop  mulu    #61865,d0
        swap.w  d0
        move.w  d0,d1
        lsr.w   #6,d1
        move.w  d1,(a2)+
        dbra    d7,.ploop
        ENDC

        clr.w   (a2)+ ; fw_LspLastDmaCon
        move.w  (a0)+,d7                ; instrument count-1
        move.l  a0,(a2)+                ; fw_LspInstruments, instrument tab addr
        move.l  a1,d0
.relocloop
        add.l   d0,(a0)
        addq.l  #6,a0
        add.l   d0,(a0)
        addq.l  #6,a0
        dbra    d7,.relocloop

        ; do not stress about this rept, your exe packer will enjoy it
        REPT    16
        move.l  a0,a1
        adda.w  (a0)+,a1
        move.l  a1,fw_LspLoopStreams-fw_LspStreams(a2)      ; set loopStreams at 0 by default
        move.l  a1,(a2)+
        ENDR
        bset.b  #1,$bfe001              ; disabling this fucking Low pass filter!!

        rts

;------------------------------------------------------------------
;
;   LSP_MusicPlayTickNano
;
;       In: a5: should be $dff000
;       Out:None
;
;------------------------------------------------------------------
LSP_MusicPlayTickNano:
        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_LspPeriodTable(a6),a4
        lea     fw_LspResetv(a6),a3
        lea     aud+4*ac_SIZEOF(a5),a2
        moveq.l #4-1,d7
.vloop  lea     -ac_SIZEOF(a2),a2
        move.l  (a1),a0
        move.b  (a0)+,d1        ; cmd for current voice
        move.l  a0,(a1)         ; update cmd stream ptr
        move.w  d1,d0
        addq.l  #4,a1
        add.b   d0,d0
        bcc.s   .novol
        move.l  (a1),a0
        moveq.l #0,d1
        move.b  (a0)+,d1
        move.l  a0,(a1)
        move.w  d1,ac_vol(a2)
.novol  addq.l  #4,a1
        add.b   d0,d0
        bcc.s   .noper
        move.l  (a1),a0
        moveq.l #0,d1
        move.b  (a0)+,d1
        move.l  a0,(a1)
        move.w  (a4,d1.w),ac_per(a2)
.noper  addq.l  #4,a1
        add.b   d0,d0
        bcc.s   .noinstr
        move.l  (a1),a0
        moveq.l #0,d1
        move.b  (a0)+,d1
        move.l  a0,(a1)

        ; prepare instrument
        move.l  fw_LspInstruments(a6),a0
        mulu    #12,d1
        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
        addq.l  #4,a1
        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
