home *** CD-ROM | disk | FTP | other *** search
/ Fujiology Archive / fujiology_archive_v1_0.iso / !FALCON / LINEOUT / OUT.ZIP / SOURCE.ZIP / RSNDEARX.ASM < prev    next >
Assembly Source File  |  2003-05-10  |  11KB  |  448 lines

  1. ;==========================================================================
  2. ; realsound mixer hack by earx (for qdsp)
  3. ; original code by newface
  4. ;
  5. ; we use from y:$3BF8 to y:$4000 (from p:$3BF8 to p:$4000)
  6. ;    and from x:$3000 to x:$3BA8 (from p:$7000 to p:$7BA8)
  7. ; we use R7 M7 for SSI transmit !
  8.  
  9. ;= equates =================================================================
  10.  
  11. PBC:        =    $FFE0                    ;Port B Control register
  12. PCC:        =    $FFE1                    ;Port C Control register
  13. PCDDR:        =    $FFE3                    ;Port C Data Direction Register
  14. HCR:        =    $FFE8                    ;Host Control Register
  15. HSR:        =    $FFE9                    ;Host Status Register
  16. HRX:        =    $FFEB                    ;Host Receive Register
  17. HTX:        =    $FFEB                    ;Host Transmit Register
  18. CRA:        =    $FFEC                    ;SSI Control Register A
  19. CRB:        =    $FFED                    ;SSI Control Register B
  20. TX:        =    $FFEF                    ;SSI Serial Transmit data/shift register
  21. IPR:        =    $FFFF                    ;Interrupt Priority Register
  22.  
  23. size_buffer:    =    $0A00
  24.  
  25. ;= macros ==================================================================
  26.  
  27. rhost:    MACRO    dest
  28.     jclr    #0,x:<<HSR,*
  29.     movep    x:<<HRX,\1
  30.     ENDM
  31.  
  32. whost:    MACRO    source
  33.     jclr    #1,x:<<HSR,*
  34.     movep    \1,x:<<HTX
  35.     ENDM
  36.  
  37. ;= vectors =================================================================
  38.  
  39.     org    P:0
  40.     jmp    >start
  41.     
  42.     org    P:$10
  43.     movep    x:(r7)+,x:<<TX
  44.     nop
  45.     movep    x:(r7)+,x:<<TX                    ; transmit exception
  46.     nop
  47.  
  48.     org    P:$26
  49.     jsr    >mix
  50.     jsr    >load
  51.  
  52. ;= main code ===============================================================
  53.     
  54.     org    P:$4000+$3000+size_buffer+30
  55.  
  56. ; Initialize the mixer..
  57. start:    bclr    #3,x:<<HCR
  58.     movep    #>1,x:<<PBC                    ;Host enable
  59.     movep    #>$04,x:<<HCR                    ;Host Command
  60.     movep    #>$3800,x:<<IPR                 ;SSI en IPL3, Host en IPL2
  61.     movep    #>$4100,x:<<CRA                    ;SSI en 2 mots/frame, 16 bits
  62.     movep    #>$0800,x:<<CRB                    ;SSI off
  63.     movep    #>$01f8,x:<<PCC                    ;Port C en SSI
  64.     movep    #>$0008,x:<<PCDDR                ;Idem
  65.     andi    #%11110000,mr        
  66.     jsr    init_buffer
  67.     bset    #3,x:<<HCR                    ;fin d'initialisation (sources de plantages...)
  68.     jmp    *
  69.  
  70. ;= program loader interrupt ================================================
  71. ;
  72. ; Note: kills registers, no overlap checking!
  73. ;
  74.  
  75. load:    movec    #$FFFF,m0                    ; Set all adr-regs to linear!
  76.     movec    m0,m1
  77.     movec    m0,m2
  78.     movec    m0,m3
  79.     movec    m0,m4
  80.     movec    m0,m5
  81.     movec    m0,m6
  82.     andi    #<$F0,mr                    ; Allow interrupts.
  83.     move    #>load_register,r1
  84.      movec    #<0,sp                        ; Reset sp, cos level0 program has sp=0!
  85.     ori    #<1,mr                        ; Allow interrupts, except IPL0.
  86.  
  87. restart:jsr    (r1)
  88.      move    x0,n2
  89.     move    #list_cmd,r2
  90.      nop
  91.      move    p:(r2+n2),r2
  92.     nop
  93.      jmp    (r2)
  94.  
  95.     dc    0
  96. list_cmd:
  97.     dc    memoryp
  98.     dc    memoryx
  99.     dc    memoryy
  100.  
  101. memoryp:jsr    (r1)
  102.      move            x0,r0
  103.      jsr    (r1)
  104.      do    x0,_loop
  105.      rhost    p:(r0)+
  106. _loop:     jmp    restart
  107.  
  108. memoryx:jsr    (r1)
  109.      move            x0,r0
  110.      jsr    (r1)
  111.      do    x0,_loop
  112.      rhost    x:(r0)+
  113. _loop:    jmp    restart
  114.  
  115. memoryy:jsr    (r1)
  116.     move            x0,r0
  117.     jsr    (r1)
  118.     do    x0,_loop
  119.     rhost    y:(r0)+
  120. _loop:    jmp    restart
  121.     
  122. load_register:
  123.     rhost    x0
  124.     rts
  125.     
  126. ;= mixer interrupt =========================================================
  127. ;
  128. ; mixtime < consumptiontime = frametime - tick
  129. ; This holds only if tick and C are small enough.
  130. ;
  131. ; Mixtime is linear to mixlength is linear to tick:
  132. ; mixtime=C*mixlength=C*framesize*tick/frametime
  133. ; C is time per mixsampleword (relative to 1/speed).
  134. ;
  135. ; Worstcase: 49KHz gives 983 words per 20ms tick. 1280-983=297 words left.
  136. ; This means 6ms to do your stuff, certainly enough for 8chn.
  137. ; At 33KHz, you have almost 20ms to get the job done.
  138. ;
  139. ; Concluding: never ever make a tick longer than 20ms.
  140. mix:    jsr    save_reg
  141.     bclr    #3,x:<<HCR
  142.     rhost    a
  143.     tst    a
  144.     jeq    coupe
  145. ; Space between ptr_buf (log) and r7 (phys) is forbidden zone.
  146. ; The rest can be used for mixing.
  147.     clr    a        y:ptr_buf,r6
  148.     movec    #size_buffer-1,m6
  149.     move            a,y:control_data
  150.     move            a,y:move            ; Indicate l/r not moved yet!
  151.     move            r7,a
  152.     move            r6,x0
  153.     sub    x0,a        #>size_buffer,x0        ; a=phys-log_end
  154.     jgt    _go_for_that
  155.     add    x0,a
  156. _go_for_that:
  157.     asr    a        #<2,n6                ; a=mixlength
  158.     move            #<2,n1
  159.     move            #<2,n2
  160.     move            a,y:loop
  161.     jsr    copy_double_dest
  162.     move            r6,r3                ; x:r6=r3=mixbuffer (left)
  163.  
  164. _voiceloop:
  165.     rhost    a                        ; a=mixcommand
  166.     move            #>$1234,x0            ; x0=terminator
  167.     cmp    x0,a        r3,r6                ; Test for terminator, r6:left
  168.     jeq    _end_mixing                    ; If it's the terminator, end mixing.
  169.     move            a1,y:control_data        ; Store commandflags.
  170.     jsr    receive_sample                    ; Store sample from host to samplebuffer.
  171.     move            (r6)+                ; r6=right
  172.     btst    #0,y:control_data                ; Test if left..
  173.     tcc    x0,b        r3,r6                ; if left then r6:left, else r6:right
  174.     jcs    _voix_droite
  175.     bset    #0,y:move                    ; Indicate l used.
  176.     jmp    _next
  177. _voix_droite:
  178.     bset    #1,y:move                    ; Indicate r used.
  179.  
  180. ; Mix this voice and proceed to next..
  181. _next:    move            #calc_freq_voice_move,r2
  182.     move            #calc_freq_voice_add,r1
  183.     btst    #1,y:control_data                ; Test if voice is moved or added.
  184.     tcs    x0,b        r2,r1                ; if moved r1:moverout, else r1:addrout
  185.     move            y:loop,n3            ; n3=#samplewords to mix
  186.     clr    b        y:vol_sample,y0            ; y0=volume
  187.     move            y:freq_sample,b0
  188.     asl    b        #buffer_inter,r2        ; b=freq, r2:splbuffer
  189.     move            b1,x1
  190.     move            b0,x0                ; x=freq
  191.     move            r2,a                ; a1:splbuffer
  192.     jsr    (r1)                        ; And mix it.
  193.     jmp    _voiceloop
  194.  
  195. ; All tracks done. If l/r unused -> clear
  196. _end_mixing:
  197.     jsr    copy_double_dest
  198.     move            y:loop,b            ; b=#samplewords mixed
  199.     tst    b        b,n3                ; n3=#samplewords mixed
  200.     jeq    _clearing_done
  201.  
  202. ; Store next buffer pointer..
  203.     movec            m6,m3                ; Set r3 to size_buffer modulo operation.
  204.     move            r3,r2                ; r2=ptr[n]
  205.     move            (r3)+n3                ; a=ptr[n]+loop
  206.     move            (r3)+n3                ; a=ptr[n+1]=ptr[n]+loop*2
  207.     move                    y:move,x0    ; x0=y:move
  208.     move            r3,y:ptr_buf            ; Store ptr[n+1].
  209.  
  210.     jset    #0,x0,_no_clr_left_data
  211.     clr    a        r2,r6                ; r6: left
  212.     do    b,_no_clr_left_data                ; Clear left chan.
  213.     move            a,x:(r6)+n6
  214. _no_clr_left_data
  215.  
  216.     move            (r2)+
  217.     jset    #1,x0,_no_clr_right_data
  218.     clr    a        r2,r6                ; r6: right
  219.     do    b,_no_clr_right_data                ; Clear right.
  220.     move            a,x:(r6)+n6
  221. _no_clr_right_data
  222.  
  223. _clearing_done:
  224.     movep    #>$5800,x:<<CRB                    ; ssi on
  225.     bset    #3,x:<<HCR
  226.     jsr    restore_reg
  227.     rti
  228.  
  229. ; Swaps mixingloops with current program in internal p mem.
  230. copy_double_dest:
  231.     move            #mix_moved,r1            ; r1:source
  232.     move            #<11,a1                ; a1=#words
  233.     move            #<$40,r2            ; r2:dest
  234.     do    a1,_loop
  235.     move    p:(r1),a
  236.     movem    p:(r2),x0
  237.     move    x0,p:(r1)+
  238.     move    a,p:(r2)+
  239. _loop:    rts
  240.  
  241. ; Receive an 8b sample from host.
  242. receive_sample:
  243.     rhost    y:vol_sample                    ; Store volume.
  244.     rhost    x0                        ; x0=frequency
  245.     move            x0,y:freq_sample        ; Store frequency.
  246.     move            y:loop,x1            ; x1: #spls to mix
  247.     mpy    x0,x1,a        #buffer_inter,r1        ; r1: start of buffer (even)
  248.     whost    a                        ; a=#spls (bytes)
  249.     lsr    a        #buffer_inter+1,r2        ; a=#pairs, r2: start of buffer (odd)
  250.     jeq    _loop_nothing                    ; if #pairs=0 -> end
  251.     rhost    x0                        ; x0= cpu start address
  252.     rhost    b                        ; b= negociated #pairs
  253.     tst    b        #>$8000,x1            ; x1=scalar
  254.     jeq    _loop_nothing
  255.     sub    b,a        b,y0                ; a= size of empty tail /2, y0=#pairs
  256.     jclr    #0,x0,_even_parity
  257.     rhost    y:(r1)+                        ; Read and store 1st off spl.
  258.     move            (r2)+
  259. _even_parity:
  260.     rhost    x0                        ; x0=first pair (xx<<16+spl[0]<<8+spl[1])
  261.     mpy    x0,x1,a        a,y1                ; a0=spl[1]<<16, a1=xx<<8+spl[0], y1=tailsize/2
  262.     move            a1,x0                ; x0=xx<<8+spl[0]
  263.     mpy    x0,x1,b                a0,y:(r2)+n2    ; b0=spl[0]<<16, Store spl[1]<<16.
  264.  
  265.     do    y0,_transloop                    ; n=2
  266.     rhost    x0                        ; x0=spl[n]<<8+spl[n+1]
  267.     mpy    x0,x1,a                b0,y:(r1)+n1    ; a0=spl[n+1]<<16, a1=spl[n], Store spl[n-2]<<16.
  268.     move            a1,x0                ; x0=spl[n]
  269.     mpy    x0,x1,b                a0,y:(r2)+n2    ; b0=spl[n]<<16, Store spl[n+1]<<16.
  270. _transloop:
  271.     move                    b0,y:(r1)+n1    ; Store beforelast sample...
  272.  
  273. ; Clear rest of buffer..
  274.     clr    b        y1,a                ; a=tailsize/2
  275.     tst    a
  276.     jeq    _empty_loop
  277.     do    y1,_empty_loop                    ; Clear tailsize/2 pairs.
  278.     move                    b,y:(r1)+n1
  279.     move                    b,y:(r2)+n2
  280. _empty_loop:
  281.  
  282. ; n+1 (+1 odd) words read.
  283.     rts
  284.  
  285. _loop_nothing
  286.     clr    a
  287.     move                    a,y:(r1)
  288.     rts
  289.  
  290. calc_freq_voice_move:
  291.     add    x,a        y:(r2),y1            ; y1=first source sample
  292.     mpy    y1,y0,b        a,r2                ; b=first mixed sample
  293.     jmp    <$40                        ; mix_moved in internal p-ram
  294.  
  295. calc_freq_voice_add:
  296.     add    x,a        x:(r6),b            ; b=first chansample
  297.     move            y:(r2),y1            ; y1=first source sample
  298.     mac    y1,y0,b        a,r2                ; b=first mixed sample
  299.     jmp    <$45                        ; mix_added in internal p-ram
  300.  
  301. ;= mixing innerloops =======================================================
  302. ;
  303. ; These loops are relocated to internal p ram..
  304. ; So the loop addresses are adjusted to their relocated adrs.
  305. ;
  306.  
  307. ; todo: remove testcity!
  308.  
  309. ; this calculates 1 sample twice, but this bug was also in the org player.
  310. mix_moved:
  311.     do    n3,$44                        ; $40, 2
  312.     add    x,a         b,x:(r6)+n6    y:(r2),y1    ; $42, 1
  313.     mpy    y1,y0,b        a,r2                ; $43, 1
  314.     rts                            ; $44, 1
  315.                                 ; $45
  316. mix_added:
  317.     do    n3,$4A                        ; $45, 2
  318.     add    x,a        b,x:(r6)+n6            ; $47, 1
  319.     move            x:(r6),b    y:(r2),y1    ; $48, 1
  320.     mac    y1,y0,b        a,r2                ; $49, 1
  321.     rts                            ; $4A, 1
  322.                                 ; $4B
  323.  
  324. ;= mixer housekeeping routines ==============================================
  325. ;
  326.  
  327. ; Cut sound and return from interrupt.
  328. coupe:    movep    #$0800,x:<<CRB                    ;SSI off
  329.     jsr    restore_reg
  330.     rti
  331.  
  332. init_buffer:
  333.     clr    a        #buffer,r7            ;init_addresse
  334.     rep    #size_buffer
  335.     move            a,x:(r7)+
  336.     move            #buffer_inter,r6        ;init_addresse
  337.     rep    #1024
  338.     move            a,y:(r6)+
  339.     move            #buffer,r7            ;init_addresse
  340.     move            #buffer,r6            ;init_addresse
  341.     movec    #size_buffer-1,M7
  342.     move            r6,y:ptr_buf
  343.     rts
  344.  
  345. save_reg:
  346.     andi    #%01010011,mr                    ;Virer: NO(scaling, trace, loop)
  347.     move            r1,x:>sauve
  348.     move            #>sauve+1,r1
  349.     nop
  350.     move            r6,x:(r1)+
  351.     move            m6,x:(r1)+
  352.     move            n6,x:(r1)+
  353.     move            r2,x:(r1)+
  354.     move            m2,x:(r1)+
  355.     move            n2,x:(r1)+
  356.     move            r3,x:(r1)+
  357.     move            m3,x:(r1)+
  358.     move            n3,x:(r1)+
  359.     move            a2,x:(r1)+
  360.     move            a1,x:(r1)+
  361.     move            a0,x:(r1)+
  362.     move            b2,x:(r1)+
  363.     move            b1,x:(r1)+
  364.     move            b0,x:(r1)+
  365.     move            x0,x:(r1)+
  366.     move            x1,x:(r1)+
  367.     move            y0,x:(r1)+
  368.     move            n1,x:(r1)+
  369.     move            y1,x:(r1)+
  370.     move            m1,x:(r1)+
  371.     movec    #-1,m1
  372.     movec    m1,m2
  373.     movec    m1,m3
  374.     move            #>resend1,r1            ;par NULLOS/DNT
  375.     move            #'RSP',x0            ;Identification du mixeur
  376.     tfr    x0,a        x0,y0                ;
  377.     whost    x0                        ;On l'envoie au 030, les deux
  378. _link    move            y0,y1                ;tests étant en quinconce.
  379.     move            a,y0
  380.     rhost    a                        ;Attendre celui donné par le 030,
  381.     cmp    x0,a                        ;en notant un éventuel envoi Host
  382.     jne    _link                        ;interrompu.
  383.     whost    y0                        ;Echange avec le 030 ce que l'on
  384.     whost    y1                        ;a intercepté.
  385.     rhost    y:(r1)+                        ;
  386.     rhost    y:(r1)+                        ;
  387.     rts
  388.     
  389. restore_reg:
  390.     move            #'RSP',x0            ;Remplir le port Host avec ce
  391.     move            #>resend1,r1            ;qu'il contenait au moment de
  392.  
  393.     do    #2,_loop
  394.     move                    y:(r1)+,a    ;du 68030...
  395.     cmp    x0,a
  396.     jeq    _nosend
  397.  
  398.     whost    a                        ; test!
  399. ;    movep    a,x:<<HTX
  400.  
  401. _nosend    nop
  402. _loop:
  403.     move            #>sauve+1,r1
  404.     nop
  405.     move            x:(r1)+,r6
  406.     move            x:(r1)+,m6
  407.     move            x:(r1)+,n6
  408.     move            x:(r1)+,r2
  409.     move            x:(r1)+,m2
  410.     move            x:(r1)+,n2
  411.     move            x:(r1)+,r3
  412.     move            x:(r1)+,m3
  413.     move            x:(r1)+,n3
  414.     move            x:(r1)+,a2
  415.     move            x:(r1)+,a1
  416.     move            x:(r1)+,a0
  417.     move            x:(r1)+,b2
  418.     move            x:(r1)+,b1
  419.     move            x:(r1)+,b0
  420.     move            x:(r1)+,x0
  421.     move            x:(r1)+,x1
  422.     move            x:(r1)+,y0
  423.     move            x:(r1)+,n1
  424.     move            x:(r1)+,y1
  425.     move            x:(r1)+,m1
  426.     move            x:>sauve,r1
  427.     rts
  428.  
  429. end_prog:
  430.  
  431. ;= data ====================================================================
  432.  
  433.         org    X:$3000
  434. buffer:        ds    size_buffer
  435. sauve:        ds    30
  436. end_x_mem:
  437.  
  438.         org    Y:$3C00-8
  439. move:        ds    1
  440. ptr_buf:    ds    1
  441. control_data:    ds    1
  442. resend1:    ds    2
  443. vol_sample:    ds    1
  444. freq_sample:    ds    1
  445. loop:        ds    1
  446. buffer_inter:    ds    1024    
  447. end_y_mem:
  448.