home *** CD-ROM | disk | FTP | other *** search
/ Fujiology Archive / fujiology_archive_v1_0.iso / !FALCON / LINEOUT / OUT.ZIP / SOURCE.ZIP / EARXPLAO.S < prev    next >
Text File  |  2003-03-22  |  46KB  |  2,060 lines

  1. ; Earx's modplayer. Based on rsnd player.
  2. ;
  3. ; Just a plain modplayer. Needs no special format. Also no extra mem
  4. ; needed after mod.
  5. ;
  6. ; Replay is on time and looping is slick. There is crap tho:
  7. ; - no fineposition in samples
  8. ; - sample-changes without note (should be seamless, now it sounds shitty)
  9. ; - tremelo bug (?)
  10. ;
  11. ; Credits:
  12. ; - cpu part:     earx, huge parts by newface (and pt author ?)
  13. ; - dsp part:     original by newface, remake by earx
  14. ; - host restore: nullos
  15. ;
  16. ; v1.1: fixed crunchy noises, upped volume, retrig working
  17. ; v1.2: optimised sampletransfer for speed
  18.  
  19. ;= equates =================================================================
  20.  
  21. color:            =    0        ; display cpu/dsp time
  22. EarxPlay.MAX_TRACKS:    =    8
  23. EarxPlay.SYNCMODE:    =    1        ; use $800 for end-command..
  24.  
  25.  
  26. DSP_BASE:        =    $FFFFA200
  27.  
  28. ; offsets of the mod's samples
  29.             RSRESET
  30. ModSample.NAME:        RS.B    22
  31. ModSample.LENGTH:    RS.W    1
  32. ModSample.FINETUNE:    RS.B    1
  33. ModSample.VOLUME:    RS.B    1
  34. ModSample.LOOPSTART:    RS.W    1
  35. ModSample.LOOPLEN:    RS.W    1
  36. ModSample.SIZE:        RS.B    0
  37.  
  38. ; offsets of the mod.format
  39.             RSRESET
  40. Mod.NAME:        RS.B    20
  41. Mod.SAMPLES:        RS.B    ModSample.SIZE*31
  42. Mod.POSITIONS:        RS.B    1
  43. Mod.REPEAT:        RS.B    1
  44. Mod.POSTABLE:        RS.B    128
  45. Mod.ID:            RS.L    1
  46. Mod.PATTERNS:        RS.B    0
  47.  
  48. ; voicestructure for administration
  49.             RSRESET
  50. Voice.CMD:        RS.B    1
  51. Voice.SAMPLE:        RS.B    1        ; sample nr
  52. Voice.COMMANDPARS:    RS.W    1
  53. Voice.IPERIOD:        RS.W    1        ; 1/f
  54. Voice.NPERIOD:        RS.W    1        ; 1/f
  55. Voice.START:        RS.L    1
  56. Voice.LENGTH:        RS.L    1
  57. Voice.LOOPSTART:    RS.L    1
  58. Voice.REPLEN:        RS.L    1
  59. Voice.SPLOFFSET:    RS.W    1
  60. Voice.TONEPORTSPEED:    RS.W    1
  61. Voice.WAVESTART:    RS.L    1
  62. Voice.REALLENGTH:    RS.L    1
  63. Voice.PATTPOS:        RS.W    1
  64. Voice.WANTEDPERIOD:    RS.W    1
  65. Voice.VOLUME:        RS.W    1
  66. Voice.FINETUNE:        RS.B    1
  67. Voice.SINFO:        RS.B    1
  68. Voice.GLISSFUNK:    RS.W    1    +0    :    +1
  69. Voice.VIBRATOCMD:    RS.W    1    +0    :    +1
  70. Voice.TREMOLOCMD:    RS.W    1    +0    ;    +1
  71. Voice.WAVECONTROL:    RS.W    1    +0    ;    +1
  72. Voice.LOOPCOUNT:    RS.W    1
  73. Voice.TONEPORTDIRECT:    RS.B    1
  74. Voice.VIBRATOPOS:    RS.B    1
  75. Voice.TREMOLOPOS:    RS.B    1
  76. Voice.FUNKOFFSET:    RS.B    1
  77. Voice.TRIGGER:        RS.B    1
  78. Voice.SAMPLENUM:    RS.B    1
  79. Voice.SIZE:        RS.B    0
  80.  
  81. ; voicestructure for mixing
  82.             RSRESET
  83. Mixer.VOLUME:        RS.W    1    
  84. Mixer.FINETUNE:        RS.B    1
  85. Mixer.INFO:        RS.B    1
  86. Mixer.PERIOD:        RS.W    1
  87. Mixer.START:        RS.L    1
  88. Mixer.LENGTH:        RS.L    1
  89. Mixer.LOOPSTART:    RS.L    1
  90. Mixer.LOOPLENGTH:    RS.L    1
  91. Mixer.SAMPLEADR:    RS.L    1
  92. Mixer.FLAGINFO:        RS.W    1
  93. Mixer.SIZE:        RS.B    0
  94.  
  95. ;= macros ==================================================================
  96.  
  97. ;    toutes le macro        NEW-FACE
  98. env    MACRO
  99. .\@    btst    #1,\1
  100.     beq.s    .\@
  101.     endm
  102. rec    MACRO
  103. .\@    btst    #0,\1
  104.     beq.s    .\@
  105.     endm
  106.  
  107. ReadHost    MACRO    dst            
  108. .\@    btst    #0,DSP_BASE+2.w
  109.     beq.s    .\@
  110.     move.l    DSP_BASE+4.w,\1
  111.     ENDM
  112. WritHost    MACRO    src                
  113. .\@    btst    #1,DSP_BASE+2.w
  114.     beq.s    .\@
  115.     move.l    \1,DSP_BASE+4.w
  116.     ENDM
  117.  
  118. save_host:    macro
  119.     move.b    #$80+$13,DSP_BASE+1.w        ;HOST commande $13
  120.     move.w    #1000,d0        
  121. .loop    tst.b    DSP_BASE+1.w            ;Attendre le déclenchement coté DSP
  122.     dbpl    d0,.loop    
  123.     move.l    #'RSP',d3            ;"Real Sound Player"
  124.     move.l    d3,d2                ;On va recevoir au maximum 2 valeurs+"RSP"
  125.     move.l    d3,d1                ;Principe des "registres en décalages"
  126. .link    move.l    d1,d0            
  127.     move.l    d2,d1                ;
  128.     ReadHost    d2            ;récupere ds le Host...
  129.     cmp.l    d3,d2                ;="RSP" ?
  130.     bne.s    .link                ;Non, on recommence
  131.     WritHost    d3            ;Balance notre identification, et lire
  132.     ReadHost    -(sp)            ;ce que le mixer a capté pour Host->DSP
  133.     ReadHost    -(sp)        
  134.     WritHost    d0            ;On lui envoie ce que l'on a capté.
  135.     WritHost    d1        
  136.     endm
  137.  
  138. restore_host:    macro
  139. ; a5: DSP_BASE+2
  140. .wc    btst    #3,(a5)                ;on attend la fin du traitement
  141.     beq.s    .wc                ;par le DSP
  142.     moveq    #1,d0            
  143. .resend    move.l    (sp)+,d1            ;On restitue au DSP 
  144.     cmpi.l    #'RSP',d1            ;le(s) valeurs qu'on
  145.     beq.s    .nosend                ;a récupéré au
  146.  
  147. ;    move.l    d1,2(a5)            ;déclenchement de la commande
  148.     WritHost    d1            ; test!
  149.  
  150. .nosend    dbf    d0,.resend        
  151.     endm
  152.  
  153. se_period    macro    adresse_table,valeur a rechercher,offset dans la table (-2), increment (variable)
  154.     moveq    #0,\3
  155.     moveq    #37,\4
  156. .loop    lsr    \4
  157.     addx    \4,\3
  158. .loop2    cmp    -2(\1,\3*2),\2
  159.     blt.s    .loop
  160.     beq.s    .find
  161.     lsr    \4
  162.     subx    \4,\3
  163.     bra.s    .loop2
  164. .find
  165.         endm
  166.  
  167. se_period2    macro    adresse_table, valeur a rechercher, compteur
  168.     moveq    #3,\3
  169. .loop    lea    8*2(\1),\1
  170.     cmp    (\1),\2
  171.     dbge    \3,.loop
  172.     beq.s    .find
  173.     bgt.s    .search    
  174.     lea    5*2(\1),\1
  175. .search    move    #7,\3
  176. .loop2    cmp    -(\1),\2
  177.     dblt    \3,.loop2
  178.     beq.s    .find
  179.     lea    2(\1),\1
  180. .find
  181. ;    \1
  182.     endm
  183.     
  184. ;tous les effects
  185. set_wave_ctrl    macro
  186.     move.b    Voice.WAVECONTROL+1(a4),d1
  187.     btst    #2,d1
  188.     bne.s    .pt_vibnoc
  189.     clr.b    Voice.VIBRATOPOS(A4)
  190. .pt_vibnoc
  191.     btst    #6,d1
  192.     bne.s    .pt_trenoc
  193.     clr.b    Voice.TREMOLOPOS(A4)
  194. .pt_trenoc
  195.     move.l    Voice.LENGTH(A4),Mixer.LENGTH(A5)    ;Set length
  196.     move.l    Voice.START(a4),Mixer.START(a5)        ;Set start
  197. .pt_sdmaskp
  198.     move.w    Voice.NPERIOD(A4),Mixer.PERIOD(a5)
  199.     move.b    #$FE,Mixer.FLAGINFO(a5)    ;s_ptr_sample(a5)=s_loopstart(a5)    
  200.     st    Voice.TRIGGER(A4)
  201.     endm
  202.  
  203. ;= main routs ==============================================================
  204.  
  205. EarxPlay.routTable:
  206.     bra.w    EarxPlay.relocate
  207.     bra.w    EarxPlay.init
  208.     bra.w    EarxPlay.deinit
  209.     bra.w    EarxPlay.play
  210.     bra.w    EarxPlay.stop
  211.     bra.w    EarxPlay.nextPos
  212.     bra.w    EarxPlay.getSyncInfo
  213.  
  214.  
  215. EarxPlay.relocate:
  216.     movem.l    d0-a6,-(sp)
  217.     lea    EarxPlay.routTable-$1C(pc),a0
  218.     MOVE.L    2(A0),D0
  219.     ADD.L    6(A0),D0
  220.     ADD.L    14(A0),D0
  221.     LEA    $1C(A0),A0
  222.     MOVE.L    A0,A1
  223.     MOVE.L    A0,A2
  224.     MOVE.L    A0,D1
  225.     ADD.L    D0,A1
  226.     MOVE.L    (A1)+,D0
  227.     ADD.L    D0,A2
  228.     ADD.L    D1,(A2)
  229.     MOVEQ.L    #0,D0
  230. .BOUCLE:MOVE.B    (A1),D0
  231.     CLR.B    (A1)+
  232.     TST.B    D0
  233.     BEQ.S    .FIN_RELOC
  234.     CMP.B    #1,D0
  235.     BEQ.S    .SPECIAL_BRANCH
  236.     ADD.L    D0,A2
  237.     ADD.L    D1,(A2)
  238.     BRA.S    .BOUCLE
  239. .SPECIAL_BRANCH:
  240.     LEA    $FE(A2),A2
  241.     BRA.S    .BOUCLE
  242. .FIN_RELOC
  243.     movem.l    (sp)+,d0-a6
  244.     RTS    
  245.  
  246. ; INPUT:
  247. ; d0.w= size in dspwords
  248. ; a0: p56 program
  249. Dsp.loadProgram:
  250.     tst.w    EarxPlay.initialized
  251.     bne.w    load_dsp_prg
  252.  
  253.     move.w    #$4242,-(sp)
  254.     clr.l    d1
  255.     move.w    d0,d1
  256.     move.l    d1,-(sp)
  257.     move.l    a0,-(sp)
  258.     move    #$6d,-(sp)    ; Dsp_ExecProg
  259.     trap    #14
  260.     lea    12(sp),sp
  261.     rts
  262.  
  263. ; INPUT:
  264. ; d0.w=mixfreq (1:49KHz, 2:33KHz)
  265. ; OUTPUT:
  266. ; d0.l=returncode (=0:ok, <0: error)
  267. EarxPlay.init:
  268.     cmpi.w    #1,d0
  269.     blt.s    .error
  270.     cmpi.w    #2,d0
  271.     bhi.s    .error
  272.     move.w    d0,matr_i
  273.  
  274.     tst.w    EarxPlay.initialized
  275.     bne.s    .tables_done
  276.     move.l    (table_frq-4.w,pc,d0.w*4),d2
  277.     bsr    init_freq_table
  278.     bsr    init_table_vitesse
  279.     st    EarxPlay.initialized
  280. .tables_done:
  281.  
  282.     bsr    init_sound_config
  283.     bsr    load_dsp_prog    
  284.     bsr    save_mfp 
  285.     bsr    EarxPlay.installTimer
  286.     moveq    #0,d0
  287.     rts
  288. .error:    clr.w    EarxPlay.initialized
  289.     moveq    #-1,d0
  290.     rts
  291.  
  292. EarxPlay.deinit:
  293.     bsr    restore_mfp
  294.     lea    $ffffa200.w,a6
  295.     move.b    #$80+$13,1(a6)
  296.     move.w    #1000,d0        
  297. .loop    tst.b    1(a6)            ;Attendre DSP
  298.     dbpl    d0,.loop        
  299.     clr.l    $fffffa204.w        
  300.     move.w    #1,-(A7)
  301.     move.w    #0,-(A7)
  302.     move.w    #0,-(A7)
  303.     move.w    #8,-(A7)
  304.     move.w    #0,-(A7)
  305.     move.w    #$8B,-(A7)
  306.     trap    #14
  307.     lea    12(sp),sp
  308.     move.w    #0,-(A7)
  309.     move.w    #$84,-(A7)
  310.     trap    #14
  311.     addq    #4,A7
  312.     rts
  313.  
  314. ; INPUT:
  315. ; a0: module
  316. ; OUTPUT:
  317. ; d0.l=returncode (=0: ok, <0: error)
  318. EarxPlay.play:
  319.     move.l    a0,EarxPlay.modAdr
  320.  
  321. ; Get nmbr of tracks..
  322.     move.l    Mod.ID(a0),d0
  323.     cmpi.l    #"4CHN",d0
  324.     beq    .set4Chn
  325.     cmpi.l    #"6CHN",d0
  326.     beq    .set6Chn
  327.     cmpi.l    #"8CHN",d0
  328.     beq    .set8Chn
  329.     cmpi.l    #"M.K.",d0
  330.     beq    .set4Chn
  331.     cmpi.l    #'M&k&',d0
  332.     beq    .set4Chn
  333.     cmpi.l    #'M&k&',d0
  334.     beq    .set4Chn
  335.     cmpi.l    #'M!k!',d0
  336.     beq    .set4Chn
  337.     cmpi.l    #'FLT4',d0
  338.     beq    .set4Chn
  339.     cmpi.l    #'FLT6',d0
  340.     beq    .set6Chn
  341.     cmpi.l    #'FLT8',d0
  342.     beq    .set8Chn
  343.     cmpi.l    #'CD81',d0
  344.     beq    .set8Chn
  345.     cmpi.l    #'OCTA',d0
  346.     beq    .set8Chn
  347.     cmpi.l    #'FA04',d0
  348.     beq    .set4Chn
  349.     cmpi.l    #'FA06',d0
  350.     beq    .set6Chn
  351.     cmpi.l    #'FA08',d0
  352.     beq    .set8Chn
  353.     bra    .error
  354. .end_get_tracks:
  355.  
  356. ; Get addresses of samples.
  357.     lea    Mod.POSTABLE(a0),a1
  358.     moveq    #128-1,d7
  359.     clr.l    d1
  360. .find_max_loop:
  361.     move.b    (a1)+,d0
  362.     cmp.b    d1,d0
  363.     bls.s    .next
  364.     move.b    d0,d1
  365. .next:    dbf    d7,.find_max_loop
  366.  
  367.     addq.w    #1,d1                    ; d1.w=#patterns
  368.     mulu.w    EarxPlay.numTracks,d1
  369.     lsl.l    #8,d1                    ; d1.l=size of patterns
  370.     lea    (Mod.PATTERNS,a0,d1.l),a1        ; a1: samples
  371.     lea    EarxPlay.splAdrTable,a2            ; a2: sample-adr-table
  372.     lea    Mod.SAMPLES(a0),a3            ; a3: spl descriptors
  373.     clr.l    d0
  374.     moveq    #31-1,d7
  375. .get_spladr_loop:
  376.     move.l    a1,(a2)+                ; Store sampleaddy.
  377.  
  378.     move.w    ModSample.LENGTH(a3),d0            ; d0.w=size of sample /2
  379.     lea    (a1,d0.l*2),a1                ; a1: next sample
  380.     bne.s    .spllength_okay
  381.     addq.w    #1,d0
  382.     move.w    d0,ModSample.LENGTH(a3)
  383. .spllength_okay:
  384.  
  385.     move.w    ModSample.LOOPLEN(a3),d1
  386.     bne.s    .looplength_okay
  387.     addq.w    #1,d1
  388.     move.w    d1,ModSample.LOOPLEN(a3)
  389. .looplength_okay:
  390.  
  391.     adda.w    #ModSample.SIZE,a3            ; a3: next sampledescriptor
  392.     dbf    d7,.get_spladr_loop
  393.  
  394. ; Set player-parameters to default.
  395.     move.w    #6,EarxPlay.speed
  396.     clr.w    EarxPlay.counter
  397.     clr.w    EarxPlay.position            ; Set to position 0.
  398.     move.w    #-1,EarxPlay.pattpos            ; Set to note -1, will be 0 at first play!
  399.  
  400.     bsr.s    EarxPlay.resetVoices
  401.     bsr    init_sound_config
  402.     st    EarxPlay.playing
  403.  
  404.     clr.l    d0
  405.     rts
  406. .error:    moveq    #-1,d0
  407.     rts
  408.  
  409. .set4Chn:
  410.     move.w    #4,EarxPlay.numTracks
  411.     bra    .end_get_tracks
  412. .set6Chn:
  413.     move.w    #6,EarxPlay.numTracks
  414.     bra    .end_get_tracks
  415. .set8Chn:
  416.     move.w    #8,EarxPlay.numTracks
  417.     bra    .end_get_tracks
  418.  
  419. EarxPlay.stop:
  420.     clr.w    EarxPlay.playing
  421.     move.w    #1,-(A7)
  422.     move.w    #0,-(A7)
  423.     move.w    #0,-(A7)
  424.     move.w    #8,-(A7)
  425.     move.w    #0,-(A7)
  426.     move.w    #$8B,-(A7)
  427.     trap    #14
  428.     lea    12(sp),sp
  429.     rts
  430.  
  431. EarxPlay.resetVoices:
  432.     lea    Mixer.table,a0
  433.     lea    .void(pc),a1
  434.     moveq    #EarxPlay.MAX_TRACKS-1,d0
  435. .loop_chip:
  436.     lea    Mixer.SIZE(a0),a3
  437.     clr.w    (a0)+    ;volume =0
  438.     clr.w    (a0)+
  439.     clr.w    (a0)+    ;period =0
  440.     move.l    a1,(a0)+ ;0 spladdy?
  441.     move.l    #2,(a0)+ ;4
  442.     move.l    a1,(a0)+ ;12 spladdy?
  443.     move.l    #2,(a0)+ ;16
  444.     move.l    a1,(a0)+    ;s_ptr_sample
  445.     clr.w    (a0)+    ;s_flag_info
  446.     move.l    a3,a0
  447.     dbf    d0,.loop_chip
  448.  
  449.     lea    Voice.table,a5
  450.     move.w    #(Voice.SIZE*EarxPlay.MAX_TRACKS/2)-1,d1
  451. .loop_cls_voice:
  452.     clr.w    (a5)+
  453.     dbf    d1,.loop_cls_voice
  454.     rts
  455.  
  456. .void:    dc.w    0        ; void, the only likable thing about c
  457.  
  458. EarxPlay.nextPos:
  459.     addq.w    #1,EarxPlay.position
  460.     clr.w    EarxPlay.pattpos
  461.     rts
  462.  
  463. ; Gets command-values from cyclic buffer.
  464. ; Each time a $800 command is encountered, this returns it's parameters.
  465. ; Note: $800 stops the player automaticly.
  466. ; TODO: block timer a interrupt! Otherwise commands might be skipped!!
  467. ; OUTPUT:
  468. ; d0.b=parameters ($FF: none)
  469. EarxPlay.getSyncInfo:
  470.     move.w    command_tail,d1
  471.     cmp.w    command_head,d1
  472.     beq.s    .error
  473.     move.b    (command_buffer.l,d1.w),d0
  474.     addq.w    #1,d1
  475.     andi.w    #$001F,d1
  476.     move.w    d1,command_tail
  477. .succes:rts
  478. .error:    moveq    #-1,d0
  479.     rts
  480.  
  481. ;= setup code ==============================================================
  482.  
  483. save_mfp
  484.     movem.l a0-a1,-(sp)
  485.     lea $fffffa00.w,a0
  486.     lea mfp_save,a1
  487.      move.l $134.w,(a1)+
  488.     move.b $7(a0),(a1)+
  489.     move.b $9(a0),(a1)+
  490.     move.b $13(a0),(a1)+
  491.     move.b $19(a0),(a1)+
  492.     move.b $1f(a0),(a1)+
  493.     move.W #$2300,sr
  494.     movem.l (sp)+,a0-a1
  495.     rts
  496.  
  497. EarxPlay.installTimer:
  498.     moveq #0,d0
  499.     lea $fffffa00.w,a0
  500.     ;movep.w d0,7(a0)
  501.     move.b #$40,$fffffa17.w
  502.     bclr #3,$fffffa17.w
  503.     bset #5,$fffffa07.w
  504.     bset #5,$fffffa13.w
  505.     clr.b $fffffa19.w
  506.     move.b #246,$fffffa1f.w
  507.     move.b #$7,$fffffa19.w
  508.     move.l #timer_a,$134.w
  509.     move.w #$2300,sr
  510.     rts
  511.  
  512. restore_mfp
  513.     move.w #$2700,sr
  514.     lea $fffffa00.w,a0
  515.     lea mfp_save,a1
  516.     move.l (a1)+,$134.w
  517.     move.b (a1)+,$7(a0)
  518.     move.b (a1)+,$9(a0)
  519.     move.b (a1)+,$13(a0)
  520.     move.b (a1)+,$19(a0)
  521.     move.b (a1)+,$1f(a0)
  522.     bset #3,$fffffa17.w
  523.     bclr #5,$fffffa07.w
  524.     bclr #5,$fffffa13.w
  525.     move.w    #20000,d0
  526. .atte:    nop
  527.     dbf    d0,.atte
  528.     move.w    #$2300,sr
  529.     rts
  530.  
  531. timer_a:tst.b    EarxPlay.playing
  532.     beq.s    .no_playing
  533.     ifne    color
  534.     move.l    #$ff000000,$fffff9800.w
  535.     endc
  536.     subq.b    #1,EarxPlay.timerCount
  537.     bpl.s    .no_read
  538.     move.b    EarxPlay.timerBase,EarxPlay.timerCount
  539.     movem.l    d0-a6,-(sp)
  540.     bsr    EarxPlay.playNote
  541.     bsr    EarxPlay.mix
  542.     movem.l    (sp)+,d0-a6
  543. .no_read:
  544.     ifne    color
  545.     move.l    #-1,$fffff9800.w
  546.     endc
  547. .no_playing:
  548.     rte
  549.     
  550.  
  551. init_sound_config
  552.     move.w    #1,-(A7)            protocol
  553.     move.w    matr_i,-(A7)        
  554.     move.w    #0,-(A7)            25175 KHZ
  555.     move.w    #8,-(A7)            dest=casque/HP
  556.     move.w    #1,-(A7)            source=emission DSP
  557.     move.w    #$8B,-(A7)
  558.     trap    #14
  559.     lea    12(sp),sp
  560.     move.w    #0,-(sp)            timer A
  561.     move.w    #1,-(sp)            playback
  562.     move.w    #135,-(sp)
  563.     trap    #14
  564.     addq.l    #6,sp
  565.     move.w    #0,-(A7)            ;tristate disable dsprec
  566.     move.w    #1,-(A7)            ;tristate enable dspxmit
  567.     move.w    #$89,-(A7)
  568.     trap    #14
  569.     addq    #6,sp
  570.     rts
  571.  
  572. init_freq_table
  573. ; d2.l=depth_freq
  574.     lea    freq_table,a0
  575.     moveq    #$4F,d0
  576. .loop1:    clr.l    (a0)+
  577.     dbf    d0,.loop1
  578.     move.w    #900-1,d0
  579.     moveq    #$50,d1
  580. .loop2:    move.l    d2,d4
  581.     divul.l    d1,d4:d4
  582.     move.l    D4,(a0)+
  583.     addq    #1,d1
  584.     dbf    d0,.loop2
  585. ; initialiser vitesse entrelacée.
  586.     rts
  587.  
  588. ; Translates ciaa bpm to timer a ticks.
  589. init_table_vitesse
  590.     movem.l d0-a6,-(sp)
  591.     lea    EarxPlay.timerTable,a0
  592.     clr.w    (a0)+
  593.     move.w    #254,d7
  594.     moveq    #1,d0
  595. .loop    move.l    d0,d1
  596.     mulu.w    #50*256,d1
  597.     divu.w    #$7d,d1
  598.     move.l    #12288*256,d2
  599.     divu.w    d1,d2
  600.     moveq    #0,d3
  601. .cc    cmp.w    #255,d2
  602.     ble.s    .ok
  603.     lsr.w    #1,d2
  604.     addq.w    #1,d3
  605.     bra.s    .cc
  606. .ok    move.b    d2,(a0)+            ; Store #ticks.
  607.     move.b    d3,(a0)+            ; Store mfp pre-div.
  608.     addq.w    #1,d0
  609.     dbf    d7,.loop    
  610.     movem.l (sp)+,d0-a6
  611.     rts
  612.  
  613.  
  614. load_dsp_prog:
  615.     pea    (EarxPlay.mixerEnd-EarxPlay.mixer)/3.w    
  616.     pea    EarxPlay.mixer(pc)
  617.     move.w    #$6d,-(sp)    
  618.     trap    #14        
  619.     lea    10(sp),sp        
  620. .wc    btst    #3,$fffffa202.w            ;on attend la phase d'initialisation DSP
  621.     beq.s    .wc            
  622.     rts
  623.  
  624. ; INPUT:
  625. ; d0.w=prgsize in 3byte units
  626. ; a0: dsp proggy
  627. load_dsp_prg:                    ;by NULLOS...
  628.     move.b    #$80+$14,DSP_BASE+1.w        ;declenche la host commande...
  629. .waiting:
  630.     tst.b    DSP_BASE+1.w
  631.     bmi.s    .waiting
  632. .send:    subq.l    #1,a0        
  633.     move.l    (a0)+,d1
  634. .loop:    WritHost    d1
  635.     moveq    #-1,d1
  636.     subq.w    #1,d0
  637.     beq.s    .loop
  638.     bpl.s    .send
  639.     rts
  640.  
  641. ;= actual player ===========================================================
  642.  
  643. ; Plays a line from the module. Reads and decodes notes to mixvoices.
  644. EarxPlay.playNote:
  645. ; Prepare for looping..
  646.     lea    Voice.table,a4
  647.     lea    Mixer.table,a5
  648.     move.w    EarxPlay.numTracks,d7
  649.     subq.w    #1,d7
  650.  
  651. ; Test if new notes should be read..
  652.     subq.w    #1,EarxPlay.counter        ; Decrease counter.
  653.     bgt    .update_fx            ; No counter reset -> only update fx.
  654.  
  655. ; Counter reset, could mean we progress to next line..
  656.     move.w    EarxPlay.speed,EarxPlay.counter    ; Reset counter.
  657.     tst.w    EarxPlay.pattDelayTime2
  658.     beq.s    .read_note            ; No delay -> process next line.
  659. ; There is patterndelay, try to move to next line and update fx..
  660.     bsr    EarxPlay.advanceNote
  661.     bra    .update_fx
  662.  
  663. ; patterndelay=0, time to read some notes..
  664. .read_note:
  665.     bsr    EarxPlay.advanceNote
  666.  
  667. ; Find note to play in current pattern.
  668.     movea.l    EarxPlay.modAdr,a1
  669.     movea.l    a1,a0
  670.     adda.w    #Mod.POSTABLE,a0        ; a0: position->pattern table
  671.     adda.w    #Mod.PATTERNS,a1        ; a1: patterndata
  672.     adda.w    EarxPlay.position,a0
  673.     clr.l    d0
  674.     move.b    (a0),d0                ; d0.l=pattnum
  675.     mulu.w    EarxPlay.numTracks,d0
  676.     lsl.l    #8,d0                ; d0.l=offset to desired pattern
  677.     adda.l    d0,a1                ; a1: desired pattern
  678.     move.w    EarxPlay.pattpos,d0        ; d0.w=position in pattern
  679.     mulu.w    EarxPlay.numTracks,d0        ; d0.l=offset to position in pattern
  680.     lea    (a1,d0.l*4),a1            ; a1: note on 1st track
  681.  
  682. ; Process the new notes in this line..
  683. .new_loop:
  684. ; Read protracker note..
  685.     move.w    (a1)+,d2            ; d2.w=$Ifff
  686.     move.w    (a1)+,d0            ; d0.w=$icPp
  687. ; Decode protracker note to: command+pars, instrument, period.
  688. ; instrument# I: upper nibble, i: lower nibble
  689. ; f: frequency (period)
  690. ; c: command (encoded)
  691. ; p: command parameters
  692.     move.w    d0,d1
  693.     lsr.w    #8,d1
  694.     lsr.w    #4,d1                ; d1.w=$000i
  695.     move.w    d2,d3
  696.     andi.w    #$F000,d2            ; d2.w=$I000
  697.     sub.w    d2,d3                ; d3.w=$0fff
  698.     lsr.w    #8,d2                ; d2.w=$00I0
  699.     add.w    d2,d1                ; d1.w=$00Ii
  700.     move.w    d3,Voice.IPERIOD(a4)        ; Store period (freq).
  701.     move.b    d1,Voice.SAMPLE(a4)        ; Store instrument.
  702.     move.w    d0,d3
  703.     and.w    #$0F00,d3            ; d3.w=$0c00
  704.     lsr.w    #8,d3                ; d3.w=$000c
  705.     clr.w    d1
  706.     move.b    d0,d1                ; d1.w=$00Pp
  707.     cmp.w    #$E,d3
  708.     bne.s    .no_e_effect            ; c<>$E -> not filter and not special
  709.     move.w    d0,d2
  710.     lsr.b    #4,d2                ; d2.b=$0P
  711.     beq.s    .no_e_effect            ; upper parnibble unused -> no special effect
  712.     addq.b    #1,d3
  713.     add.b    d2,d3                ; d3.b=specialcommand=P+1+c
  714.     and.b    #$0F,d1                ; d1.b=specialpars=p.
  715. .no_e_effect:
  716. ; d1.b=commandpars (still encoded)
  717.     move.b    d3,Voice.CMD(a4)        ; Store command.
  718.     jsr    (modi_comm.w,pc,d3.w*4)        ; Decode parameters for command.
  719.     move.w    d1,Voice.COMMANDPARS(a4)    ; Output commandpars. (a word for a byte, lame)
  720.  
  721. ;- ready to kick some notes ------------------------------------------------
  722.     pea    (a1)
  723.     clr.l    d0
  724.     move.b    Voice.SAMPLE(a4),d0
  725.     beq.s    .inst_nul    ;instrument nul?
  726.  
  727. ;tape le sample
  728.     subq.w    #1,d0
  729.     move.l    d0,d1
  730.     movea.l    EarxPlay.modAdr,a1        ; a1: mod
  731.     adda.w    #Mod.SAMPLES,a1            ; a1: sampledescriptors
  732.     mulu.w    #ModSample.SIZE,d0        ; d0.l=offset to sampledesciptor
  733.     adda.l    d0,a1                ; a1: desired sampledescriptor
  734.     move.l    (EarxPlay.splAdrTable,d1.l*4),d1
  735.     move.l    d1,Voice.START(a4)
  736.     clr.l    d0
  737.     move.w    ModSample.LENGTH(a1),d0
  738.     add.l    d0,d0                ; Words to bytes..
  739.     move.l    d0,Voice.LENGTH(a4)
  740.     clr.w    d0
  741.     move.b    ModSample.VOLUME(a1),d0
  742.     lsl.w    #8,d0
  743.     move.w    d0,Voice.VOLUME(a4)        ; 0<=v<=64*256
  744.     move.b    ModSample.FINETUNE(a1),Voice.FINETUNE(a4)        ; Store finetune.
  745.     clr.l    d0
  746.     move.w    ModSample.LOOPSTART(a1),d0
  747.     add.l    d0,d0                ; Words to bytes.
  748.     add.l    d1,d0
  749.     move.l    d0,Voice.LOOPSTART(a4)
  750.     move.l    d0,Voice.WAVESTART(a4)
  751.     clr.l    d0
  752.     move.w    ModSample.LOOPLEN(a1),d0
  753.     add.l    d0,d0                ; Words to bytes.
  754.     move.l    d0,Voice.REPLEN(a4)
  755.  
  756.     clr.b    Mixer.INFO(a5)
  757.  
  758. ;    voir PROTRACK    (c 1 bordel !!)
  759. .inst_nul:
  760.     clr.l    d0
  761.     move.b    Voice.CMD(a4),d0
  762. ;    cmp.b    #$E,d0
  763. ;    beq.s    .no_filter
  764. ;    bsr    pt_filteronoff
  765. ;.no_filter
  766.     tst.w    Voice.IPERIOD(a4)
  767.     beq.s    .search_command1    ;periode nul?
  768. ;    commande 3 7 9
  769.     jsr    (pt_read_pattern_table1.w,pc,d0.l*4)
  770.     bra.s    .check_for_next
  771. .search_command1
  772.     jsr    (pt_read_pattern_no_note.w,pc,d0.l*4)
  773. .check_for_next
  774.     move.w    Voice.VOLUME(a4),d0
  775.     lsr.w    #8,d0
  776.     move.w    d0,Mixer.VOLUME(a5)
  777.     move.b    Voice.FINETUNE(a4),Mixer.FINETUNE(a5)
  778.     move.l    Voice.LOOPSTART(a4),Mixer.LOOPSTART(a5)
  779.     move.l    Voice.REPLEN(a4),Mixer.LOOPLENGTH(a5)    
  780.     adda.w    #Mixer.SIZE,a5
  781.     adda.w    #Voice.SIZE,a4
  782.     move.l    (sp)+,a1
  783.     dbf    d7,.new_loop    
  784.     rts
  785.  
  786. .update_fx:
  787. ; Update old fx..
  788. .update_old_loop:
  789.     bsr    EarxPlay.updateFunk
  790.     move.w    Voice.NPERIOD(a4),Mixer.PERIOD(a5)
  791.     clr.l    d0
  792.     move.b    Voice.CMD(a4),d0
  793.     jsr    (EarxPlay.checkEffectsTable.w,pc,d0.l*4)
  794.     move.w    Voice.VOLUME(a4),d0
  795.     lsr.w    #8,d0
  796.     move.w    d0,Mixer.VOLUME(a5)
  797.     move.b    Voice.FINETUNE(a4),Mixer.FINETUNE(a5)
  798.     adda.w    #Mixer.SIZE,a5
  799.     adda.w    #Voice.SIZE,a4
  800.     dbf    d7,.update_old_loop
  801.     rts
  802.  
  803. ; Advances the player to next line keeping in mind delay.
  804. EarxPlay.advanceNote:
  805. ; Update pattpos and position..
  806.     move.w    EarxPlay.pattpos,d0        ; d0.w=old patternposition
  807.     addq.w    #1,d0                ; d0.w='new' pattpos
  808.  
  809. ; delay shit..
  810.     move.w    EarxPlay.pattDelayTime2,d2
  811.     move.w    EarxPlay.pattDelayTime,d1
  812.     beq.s    .pt_dskpc
  813.     move.w    d1,d2
  814.     clr.w    EarxPlay.pattDelayTime
  815. .pt_dskpc:
  816.     tst.w    d2
  817.     beq.s    .no_ptdskpa
  818.     subq.w    #1,d2
  819.     beq.s    .no_ptdskpa
  820.     subq.w    #1,d0    
  821. .no_ptdskpa:
  822.     move.w    d2,EarxPlay.pattDelayTime2
  823.  
  824.     cmpi.w    #64,d0
  825.     blo.s    .pattpos_ok
  826.     clr.w    d0                ; Reset patternposition.
  827.     move.w    EarxPlay.position,d1        ; d1.w=(old) position
  828.     addq.w    #1,d1                ; Increase position.
  829.     movea.l    EarxPlay.modAdr,a0
  830.     cmp.b    Mod.POSITIONS(a0),d1
  831.     blt.s    .pos_ok
  832.     clr.w    d1
  833.     move.b    Mod.REPEAT(a0),d1        ; Wrap position.
  834.     cmp.b    Mod.POSITIONS(a0),d1
  835.     blt.s    .pos_ok
  836.     clr.w    d1
  837. .pos_ok:move.w    d1,EarxPlay.position        ; Store position.
  838. .pattpos_ok:
  839.     move.w    d0,EarxPlay.pattpos        ; Store patternposition.
  840.     rts
  841.  
  842. ;= effect tables ===========================================================
  843.  
  844. pt_funktable
  845.     dc.b 0,5,6,7,8,10,11,13,16,19,22,26,32,43,64,128
  846.  
  847. pt_vibratotable    
  848.     dc.b 0,24,49,74,97,120,141,161
  849.     dc.b 180,197,212,224,235,244,250,253
  850.     dc.b 255,253,250,244,235,224,212,197
  851.     dc.b 180,161,141,120,97,74,49,24
  852.  
  853. pt_periodtable
  854. ; -> Tuning 0
  855.     dc.w    856,808,762,720,678,640,604,570,538,508,480,453
  856.     dc.w    428,404,381,360,339,320,302,285,269,254,240,226
  857.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113,0
  858. ; -> Tuning 1
  859.     dc.w    850,802,757,715,674,637,601,567,535,505,477,450
  860.     dc.w    425,401,379,357,337,318,300,284,268,253,239,225
  861.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113,0
  862. ; -> Tuning 2
  863.     dc.w    844,796,752,709,670,632,597,563,532,502,474,447
  864.     dc.w    422,398,376,355,335,316,298,282,266,251,237,224
  865.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112,0
  866. ; -> Tuning 3
  867.     dc.w    838,791,746,704,665,628,592,559,528,498,470,444
  868.     dc.w    419,395,373,352,332,314,296,280,264,249,235,222
  869.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111,0
  870. ; -> Tuning 4
  871.     dc.w    832,785,741,699,660,623,588,555,524,495,467,441
  872.     dc.w    416,392,370,350,330,312,294,278,262,247,233,220
  873.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110,0
  874. ; -> Tuning 5
  875.     dc.w    826,779,736,694,655,619,584,551,520,491,463,437
  876.     dc.w    413,390,368,347,328,309,292,276,260,245,232,219
  877.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109,0
  878. ; -> Tuning 6
  879.     dc.w    820,774,730,689,651,614,580,547,516,487,460,434
  880.     dc.w    410,387,365,345,325,307,290,274,258,244,230,217
  881.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109,0
  882. ; -> Tuning 7
  883.     dc.w    814,768,725,684,646,610,575,543,513,484,457,431
  884.     dc.w    407,384,363,342,323,305,288,272,256,242,228,216
  885.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108,0
  886. ; -> Tuning -8
  887.     dc.w    907,856,808,762,720,678,640,604,570,538,508,480
  888.     dc.w    453,428,404,381,360,339,320,302,285,269,254,240
  889.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120,0
  890. ; -> Tuning -7
  891.     dc.w    900,850,802,757,715,675,636,601,567,535,505,477
  892.     dc.w    450,425,401,379,357,337,318,300,284,268,253,238
  893.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119,0
  894. ; -> Tuning -6
  895.     dc.w    894,844,796,752,709,670,632,597,563,532,502,474
  896.     dc.w    447,422,398,376,355,335,316,298,282,266,251,237
  897.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118,0
  898. ; -> Tuning -5
  899.     dc.w    887,838,791,746,704,665,628,592,559,528,498,470
  900.     dc.w    444,419,395,373,352,332,314,296,280,264,249,235
  901.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118,0
  902. ; -> Tuning -4
  903.     dc.w    881,832,785,741,699,660,623,588,555,524,494,467
  904.     dc.w    441,416,392,370,350,330,312,294,278,262,247,233
  905.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117,0
  906. ; -> Tuning -3
  907.     dc.w    875,826,779,736,694,655,619,584,551,520,491,463
  908.     dc.w    437,413,390,368,347,328,309,292,276,260,245,232
  909.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116,0
  910. ; -> Tuning -2
  911.     dc.w    868,820,774,730,689,651,614,580,547,516,487,460
  912.     dc.w    434,410,387,365,345,325,307,290,274,258,244,230
  913.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115,0
  914. ; -> Tuning -1
  915.     dc.w    862,814,768,725,684,646,610,575,543,513,484,457
  916.     dc.w    431,407,384,363,342,323,305,288,272,256,242,228
  917.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114,0
  918.  
  919. ;= command handling routs ==================================================
  920.  
  921. ; used for converting parameters in an 'easy' format.
  922. modi_comm:
  923.     bra.w    pt_parpeggio        ;0    
  924.     bra.w    return            ;1    
  925.     bra.w    return            ;2    
  926.     bra.w    return            ;pt_settoneporta    ;3
  927.     bra.w    pt_pvibrato        ;4
  928.     bra.w    pt_pvolumeslide        ;
  929.     bra.w    pt_pvolumeslide        ;
  930.     bra.w    pt_ptremolo        ;
  931.     bra.w    return            ;8
  932.     bra.w    pt_psampleoffset    ;9
  933.     bra.w    pt_pvolumeslide        ;10
  934.     bra.w    return            ;11
  935.     bra.w    pt_pvolumechange    ;12
  936.     bra.w    pt_ppatternbreak    ;13
  937.     bra.w    return            ;pt_FilterOnOff        ;14
  938.     bra.w    return            ;pt_SetSpeed        ;15
  939.     bra.w    return            ;pt_FinePortaUp        ;16
  940.     bra.w    return            ;pt_FinePortaDown    ;17
  941.     bra.w    pt_pSetGlissControl    ;18
  942.     bra.w    return            ;pt_SetVibratoControl    ;19
  943.     bra.w    pt_psetfinetune        ;20
  944.     bra.w    return            ;pt_JumpLoop        ;21
  945.     bra.w    return            ;pt_SetTremoloControl    ;22
  946.     bra.w    return            ;pt_KarplusStrong    ;23
  947.     bra.w    return            ;pt_RetrigNote        ;24
  948.     bra.w    pt_pVolumeFineUp    ;25
  949.     bra.w    pt_pVolumeFineDown    ;26
  950.     bra.w    return            ;pt_NoteCut        ;27
  951.     bra.w    return            ;pt_NoteDelay        ;28
  952.     bra.w    return            ;pt_PatternDelay    ;29
  953.     bra.w    return            ;pt_FunkIt        ;30
  954.  
  955. pt_ptremolo
  956. pt_pvibrato
  957.     lsl.w    #4,d1
  958.     lsr.b    #4,d1
  959.     rts
  960. pt_parpeggio
  961.     lsl.w    #4,d1
  962.     lsr.b    #4,d1
  963.     rts
  964. pt_psampleoffset
  965.     lsl    #8,d1    ;*256
  966.     rts
  967.  
  968. pt_pvolumeslide
  969.     and    #$ff,d1
  970.     move    d1,d2
  971.     lsr    #4,d2
  972.     tst.b    d2
  973.     beq.s    pt_pVolSlideDown
  974.     lsl    #8,d2
  975.     move    d2,d1
  976.     rts
  977.  
  978. pt_pVolSlideDown
  979.     and    #$f,d1
  980.     lsl    #8,d1
  981.     neg    d1
  982.     rts
  983.  
  984. pt_pVolumeFineUp
  985.     and    #$f,d1
  986.     lsl    #8,d1
  987.     rts
  988.  
  989. pt_pVolumeFineDown
  990.     and    #$f,d1
  991.     lsl    #8,d1
  992.     neg    d1
  993.     rts
  994.  
  995. pt_psetfinetune
  996. pt_pSetGlissControl
  997.     ;and    #$f,d1
  998.     rts
  999.  
  1000. pt_pvolumechange    
  1001.     cmp.w    #$40,d1
  1002.     ble.s    .end
  1003.     moveq    #$40,d1
  1004. .end:    rts
  1005.  
  1006. pt_ppatternbreak        ;13
  1007.     movem.l    d0/d2,-(sp)
  1008.     move.l    d1,d2
  1009.     lsr.b    #4,d1
  1010.     mulu    #10,d1
  1011.     and.w    #$f,d2
  1012.     add.w    d2,d1
  1013.     cmp.w    #63,d1
  1014.     ble.s    .end_effect
  1015.     clr.w    d1
  1016. .end_effect
  1017.     movem.l    (sp)+,d0/d2
  1018.     rts
  1019.  
  1020.  
  1021. EarxPlay.checkEffectsTable:
  1022.     bra.w    pt_arpeggio            ;
  1023.     bra.w    pt_portaup            ;    
  1024.     bra.w    pt_portadown            ;
  1025.     bra.w    pt_toneportamento        ;
  1026.     bra.w    pt_vibrato            ;
  1027.     bra.w    pt_toneplusvolslide        ;
  1028.     bra.w    pt_vibratoplusvolslide        ;
  1029. pt_SetBack
  1030.     bra.w    pt_tremolo
  1031.     bra.w    return            ;8    ;PHASOR
  1032.     bra.w    return            ;9    ;
  1033.     bra.w    pt_volumeslide            ;
  1034.     bra.w    return            ;11    ;
  1035.     bra.w    return            ;12    ;
  1036.     bra.w    return            ;13    ;
  1037.     bra.w    return            ;14    ;
  1038.     bra.w    return            ;15    ;
  1039.     bra.w    return        ;16        ;
  1040.     bra.w    return        ;17    ;
  1041.     bra.w    pt_setglisscontrol    ;18    ;
  1042.     bra.w    pt_setvibratocontrol    ;19    ;
  1043.     bra.w    pt_setfinetune    ;20        ;
  1044.     bra.w    return        ;21        ;
  1045.     bra.w    pt_settremolocontrol    ;22    ;
  1046.     bra.w    pt_karplusstrong    ;23    ;
  1047.     bra.w    pt_retrignote    ;24
  1048.     bra.w    return        ;25
  1049.     bra.w    return        ;26
  1050.     bra.w    pt_notecut    ;27
  1051.     bra.w    pt_notedelay    ;28
  1052.     bra.w    return        ;29
  1053.     bra.w    return        ;30
  1054.  
  1055.  
  1056. ;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  1057.  
  1058. pt_read_pattern_table1
  1059.     bra.w    pt_initperiod        ;
  1060.     bra.w    pt_initperiod        ;
  1061.     bra.w    pt_initperiod        ;
  1062.     bra.w    pt_chktoneporta    ;
  1063.     bra.w    pt_initperiod        ;
  1064.     bra.w    pt_chktoneporta    ;
  1065.     bra.w    pt_initperiod        ;
  1066. ;pt_SetBack
  1067.     bra.w    pt_initperiod
  1068.     bra.w    pt_initperiod        ;8    ;phasor effect ?!?
  1069.     bra.w    pt_dosampleoffset    ;9    
  1070.     rept    21
  1071.     bra.w    pt_initperiod        ;10
  1072.     endr
  1073.  
  1074. ;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  1075.  
  1076. pt_read_pattern_table2
  1077.     bra.w    return        ;
  1078.     bra.w    return        ;
  1079.     bra.w    return        ;
  1080.     bra.w    return        ;
  1081.     bra.w    return        ;
  1082.     bra.w    return        ;
  1083.     bra.w    return        ;
  1084. ;pt_SetBack
  1085.     bra.w    return
  1086.  
  1087. ;    bra.w    return            ;8    ;phasor effect ?!?
  1088.     bra.w    pt_docommand8
  1089.  
  1090.     bra.w    return            ;9    ;
  1091.     bra.w    return            
  1092.     bra.w    pt_positionjump        ;11    ;
  1093.     bra.w    pt_volumechange        ;12    ;
  1094.     bra.w    pt_patternbreak        ;13    ;
  1095.     bra.w    return            ;14    ;
  1096.     bra.w    pt_setspeed        ;15    ;
  1097.     bra.w    pt_fineportaup        ;16    ;
  1098.     bra.w    pt_fineportadown    ;17    ;
  1099.     bra.w    pt_setglisscontrol    ;18    ;
  1100.     bra.w    pt_setvibratocontrol    ;19    ;
  1101.     bra.w    pt_dosetfinetune    ;20    ;
  1102.     bra.w    pt_jumploop        ;21    ;
  1103.     bra.w    pt_settremolocontrol    ;22    ;
  1104.     bra.w    pt_karplusstrong    ;23    ;
  1105.     bra.w    pt_retrignote        ;24
  1106.     bra.w    pt_volumefineup        ;25    ;
  1107.     bra.w    pt_volumefinedown    ;26    ;
  1108.     bra.w    pt_notecut        ;27
  1109.     bra.w    pt_notedelay        ;28
  1110.     bra.w    pt_patterndelay        ;29    ;
  1111.     bra.w    pt_funkit        ;30    ;
  1112.  
  1113. ;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  1114.  
  1115. pt_read_pattern_no_note
  1116.     bra.w    return
  1117.     bra.w    return
  1118.     bra.w    return
  1119.     bra.w    return
  1120.     bra.w    return
  1121.     bra.w    return
  1122.     bra.w    return
  1123.     bra.w    return
  1124.  
  1125.     bra.w    pt_docommand8
  1126. ;    bra.w    return
  1127.  
  1128.     bra.w    pt_sampleoffset    ;9    ;
  1129.     bra.w    return            ;
  1130.     bra.w    pt_positionjump    ;11    ;
  1131.     bra.w    pt_volumechange    ;12    ;
  1132.     bra.w    pt_patternbreak    ;13    ;
  1133.     bra.w    return        ;14    ;
  1134.     bra.w    pt_setspeed    ;15    ;
  1135.     bra.w    pt_fineportaup        ;16    ;
  1136.     bra.w    pt_fineportadown    ;17    ;
  1137.     bra.w    pt_setglisscontrol    ;18    ;
  1138.     bra.w    pt_setvibratocontrol    ;19    ;
  1139.     bra.w    pt_setfinetune        ;20    ;
  1140.     bra.w    pt_jumploop        ;21    ;
  1141.     bra.w    pt_settremolocontrol    ;22    ;
  1142.     bra.w    pt_karplusstrong    ;23    ;
  1143.     bra.w    pt_retrignote        ;24    ;
  1144.     bra.w    pt_volumefineup        ;25    ;
  1145.     bra.w    pt_volumefinedown    ;26    ;
  1146.     bra.w    pt_notecut        ;27    ;
  1147.     bra.w    pt_notedelay        ;28    ;
  1148.     bra.w    pt_patterndelay        ;29    ;
  1149.     bra.w    pt_funkit        ;30    ;
  1150.  
  1151. return:    rts
  1152.  
  1153. ;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  1154.  
  1155. ; Store command-value in cyclic buffer.
  1156. pt_docommand8:
  1157.     move.w    command_head,d0
  1158.     move.b    Voice.COMMANDPARS+1(a4),d1
  1159.     IFNE    EarxPlay.SYNCMODE
  1160.     bne.s    .store
  1161. ; Command 0 : stop playing!
  1162.     movem.w    d0-d1,-(sp)
  1163.     bsr.w    EarxPlay.stop
  1164.     movem.w    (sp)+,d0-d1
  1165.     ENDC
  1166. .store:    move.b    d1,(command_buffer,d0.w)
  1167.     addq.w    #1,d0
  1168.     andi.w    #$001F,d0
  1169.     move.w    d0,command_head
  1170.     rts
  1171.  
  1172. pt_dosetfinetune
  1173.     bsr    pt_setfinetune
  1174.     bsr    pt_setperiod ;; non defini.
  1175.     rts
  1176.  
  1177. pt_chktoneporta
  1178.     bsr    pt_settoneporta
  1179.     moveq    #0,d0
  1180.     move.b    Voice.CMD(a4),d0
  1181.     jmp    (EarxPlay.checkEffectsTable.w,pc,d0.l*4)    ;effets 3 5
  1182.  
  1183. pt_dosampleoffset
  1184.     bsr    pt_sampleoffset
  1185.     bsr    pt_setperiod                ;effet 9
  1186.     set_wave_ctrl
  1187.     rts
  1188.     
  1189. pt_initperiod
  1190.     bsr.s    pt_setperiod
  1191.     moveq    #0,d0
  1192.     move.b    Voice.CMD(a4),d0
  1193.     cmp.b    #28,d0
  1194.     beq    pt_notedelay
  1195.     set_wave_ctrl
  1196.     jmp    (pt_read_pattern_table2.w,pc,d0.l*4)
  1197.     rts
  1198.  
  1199. pt_setperiod:
  1200.     lea    pt_periodtable(pc),a0
  1201.     move.w    Voice.IPERIOD(a4),d0
  1202.     clr.l    d3
  1203.     move.b    Voice.FINETUNE(a4),d3
  1204.     beq.s    .set_direcper
  1205.     se_period    a0,d0,d2,d1
  1206.     mulu    #37,D3
  1207.     add.w    d3,d2
  1208.     move    -2(a0,d2*2),Voice.NPERIOD(a4)
  1209.     rts
  1210. .set_direcper
  1211.     move    d0,Voice.NPERIOD(a4)
  1212.     rts
  1213.  
  1214. pt_arpeggio
  1215.     moveq    #0,d1
  1216.     move    EarxPlay.counter,d0
  1217.     divs    #3,d0
  1218.     swap    d0
  1219.     subq    #1,d0
  1220.     beq.s    .set_direct_period    
  1221.     bmi.s    .pt_arpegio1
  1222. .pt_arpegio2
  1223.     move.b    Voice.COMMANDPARS+1(a4),d1    
  1224.     bra.s    .next_arp
  1225. .pt_arpegio1
  1226.     move.b    Voice.COMMANDPARS(a4),d1    
  1227. .next_arp
  1228.     moveq    #0,d0
  1229.     move.b    Voice.FINETUNE(a4),d0
  1230.     mulu    #37*2,d0
  1231.     lea    pt_periodtable(pc),a0
  1232.     add.l    d0,a0
  1233.     move    Voice.NPERIOD(a4),d0
  1234.     se_period2    a0,d0,d2
  1235. .arpegio_set    
  1236.     move    (a0,d1*2),Mixer.PERIOD(a5)
  1237.     rts
  1238. .set_direct_period
  1239.     rts
  1240.  
  1241. pt_settoneporta    
  1242.     move    Voice.IPERIOD(a4),d2
  1243.     moveq    #0,d0
  1244.     move.b    Voice.FINETUNE(a4),d0
  1245.     beq.s    .set_direcper
  1246.     mulu    #37*2,d0
  1247.     lea    (pt_periodtable.w,pc,d0),a0
  1248.     se_period2    a0,d2,d0
  1249.     move.b    Voice.FINETUNE(a4),d2
  1250.     and.b    #8,D2
  1251.     beq.s    .pt_stpgoss
  1252.     subq    #2,a0
  1253. .pt_stpgoss
  1254.     move    (a0),d2    ; d'apres
  1255. .set_direcper
  1256.     move    d2,Voice.WANTEDPERIOD(a4)    
  1257.     sf    Voice.TONEPORTDIRECT(a4)
  1258.     cmp    Voice.NPERIOD(a4),d2
  1259.     beq.s    .pt_cleartoneporta    
  1260.     bge.s    .return
  1261.     st    Voice.TONEPORTDIRECT(a4)
  1262. .return
  1263.     rts
  1264. .pt_cleartoneporta
  1265.     clr.w    Voice.WANTEDPERIOD(a4)
  1266.     rts
  1267.  
  1268. pt_toneportamento
  1269.     move    Voice.COMMANDPARS(a4),d0
  1270.     beq.s    pt_toneportnochange
  1271.     clr.w    Voice.COMMANDPARS(a4)
  1272.     move    d0,Voice.TONEPORTSPEED(a4)
  1273. pt_toneportnochange
  1274.     move.w    Voice.WANTEDPERIOD(a4),d0
  1275.     beq.s    .return
  1276.     move    Voice.NPERIOD(a4),d2    ;
  1277.     move    Voice.TONEPORTSPEED(a4),d1
  1278.     tst.b    Voice.TONEPORTDIRECT(a4)
  1279.     bne.s    .pt_toneportaup
  1280. .pt_toneportadown
  1281.     add    d1,d2
  1282.     cmp    d2,d0
  1283.     bgt.s    .pt_toneportasetper
  1284.     bra.s    .set_reg
  1285. .pt_toneportaup
  1286.     sub    d1,d2
  1287.     cmp    d2,d0
  1288.     blt.s    .pt_toneportasetper
  1289. .set_reg
  1290.     move    d0,d2
  1291.     clr.w    Voice.WANTEDPERIOD(a4)
  1292. .pt_toneportasetper
  1293.     move    d2,Voice.NPERIOD(a4)
  1294.     tst.b    Voice.GLISSFUNK+1(a4)
  1295.     beq    .pt_glissskip
  1296.     moveq    #0,d0
  1297.     move.b    Voice.FINETUNE(a4),d0
  1298.     mulu    #37*2,d0
  1299.     lea    (pt_periodtable.w,pc,d0),a0
  1300.     se_period2    a0,d2,d0
  1301.     move    (a0),d2
  1302. .pt_glissskip
  1303.     move    d2,Mixer.PERIOD(a5)
  1304.     rts
  1305. .return:rts
  1306.  
  1307. pt_vibrato
  1308.     move    Voice.COMMANDPARS(a4),d0
  1309.     beq.s    pt_vibrato2
  1310.     tst.b    d0
  1311.     beq.s    .pt_vibskip    
  1312.     move.b    d0,Voice.VIBRATOCMD+1(a4)
  1313. .pt_vibskip    
  1314.     lsr.w    #8,d0
  1315.     tst.b    d0
  1316.     beq.s    pt_vibrato2    
  1317.     move.b    d0,Voice.VIBRATOCMD(a4)
  1318. pt_vibrato2
  1319.     move.b    Voice.VIBRATOPOS(a4),d0
  1320.     lea    pt_vibratotable(pc),a1
  1321.     lsr    #2,d0
  1322.     and    #$1f,d0
  1323.     moveq    #0,d2
  1324.     move.b    Voice.WAVECONTROL+1(a4),d2
  1325.     and.b    #$3,d2
  1326.     beq.s    .pt_vib_sine
  1327.     lsl.b    #3,d0
  1328.     cmp.b    #1,d2
  1329.     beq.s    .pt_vib_rampdown
  1330.     st    d2
  1331.     bra.s    .pt_vib_set
  1332. .pt_vib_rampdown
  1333.     move.b    d0,d2
  1334.     tst.b    Voice.VIBRATOPOS(a4)
  1335.     bpl.s    .pt_vib_set
  1336.     st    d2
  1337.     sub.b    d0,d2
  1338.     bra.s    .pt_vib_set
  1339. .pt_vib_sine
  1340.     move.b    (a1,d0.w),d2
  1341. .pt_vib_set
  1342.     
  1343.     move.b    Voice.VIBRATOCMD+1(a4),d0    
  1344.     mulu    d0,d2
  1345.     lsr.w    #7,d2
  1346.     
  1347.     move    Voice.NPERIOD(a4),d1
  1348.     tst.b    Voice.VIBRATOCMD(a4)
  1349.     bpl.s    .pt_vibratopos
  1350.     neg    d2
  1351. .pt_vibratopos
  1352.     add    d2,d1
  1353.     move    d1,Mixer.PERIOD(a5)
  1354.     
  1355.     move.b    Voice.VIBRATOCMD(a4),d1
  1356.     lsl.b    #4,d1
  1357.     or.b    d0,d1
  1358.     lsr.w    #2,d1
  1359.     and    #$3c,d1
  1360.     add.b    d1,Voice.VIBRATOCMD(a4)
  1361.  
  1362.     rts
  1363.  
  1364. pt_toneplusvolslide    
  1365.     bsr    pt_toneportnochange
  1366.     bra    pt_volumeslide
  1367.  
  1368. pt_vibratoplusvolslide
  1369.     bsr    pt_vibrato2
  1370.     bra    pt_volumeslide
  1371.  
  1372. pt_tremolo
  1373.     move    Voice.COMMANDPARS(a4),d0
  1374.     beq.s    pt_tremolo2
  1375.     tst.b    d0
  1376.     beq.s    .pt_treskip    
  1377.     move.b    d0,Voice.TREMOLOCMD+1(a4)
  1378. .pt_treskip    
  1379.     lsr.w    #8,d0
  1380.     tst.b    d0
  1381.     beq.s    pt_tremolo2    
  1382.     move.b    d0,Voice.TREMOLOCMD(a4)
  1383. pt_tremolo2
  1384.     move.b    Voice.TREMOLOPOS(a4),d0
  1385.     lea    pt_vibratotable(pc),a1
  1386.     lsr    #2,d0
  1387.     and    #$1f,d0
  1388.     moveq    #0,d2
  1389.     move.b    Voice.WAVECONTROL(a4),d2
  1390.     and.b    #$3,d2
  1391.     beq.s    .pt_tre_sine
  1392.     lsl.b    #3,d0
  1393.     cmp.b    #1,d2
  1394.     beq.s    .pt_tre_rampdown
  1395.     st    d2
  1396.     bra.s    .pt_tre_set
  1397. .pt_tre_rampdown
  1398.     move.b    d0,d2
  1399.     tst.b    Voice.TREMOLOPOS(a4)
  1400.     bpl.s    .pt_tre_set
  1401.     st    d2
  1402.     sub.b    d0,d2
  1403.     bra.s    .pt_tre_set
  1404. .pt_tre_sine
  1405.     move.b    (a1,d0.w),d2
  1406. .pt_tre_set
  1407.     move.b    Voice.TREMOLOCMD+1(a4),d0    
  1408.     mulu    d0,d2
  1409.     lsl    #2,d2
  1410.     move    Voice.VOLUME(a4),d0
  1411.     
  1412.     tst.b    Voice.TREMOLOPOS(a4)
  1413.     bpl.s    .pt_vibratopos
  1414.     neg    d2
  1415. .pt_vibratopos
  1416.     add    d2,d0
  1417.     bpl.s    .no_negv
  1418.     moveq    #0,d0
  1419. .no_negv
  1420.     cmp    #$4000,d0
  1421.     ble.s    .nohiv
  1422.     move    #$4000,d0
  1423. .nohiv:    lsr.w    #8,d0
  1424.     move.w    d0,Mixer.VOLUME(a5)
  1425.     move.b    Voice.TREMOLOCMD(a4),d1
  1426.     lsl.b    #4,d1
  1427.     or.b    Voice.TREMOLOCMD+1(a4),d1
  1428.     lsr.b    #2,d1
  1429.     and    #$3c,d1
  1430.     add.b    d1,Voice.TREMOLOPOS(a4)
  1431. ;    ne plus fixer le volume.
  1432.     rts
  1433.  
  1434. pt_sampleoffset    
  1435.     moveq    #0,d0
  1436.     move.w    Voice.COMMANDPARS(A4),D0
  1437.     beq.s    pt_sononew
  1438.     move.w    d0,Voice.SPLOFFSET(A4)
  1439. pt_sononew
  1440.     move.w    Voice.SPLOFFSET(A4),D0
  1441.     cmp.l    Voice.LENGTH(A4),D0
  1442.     bge.s    pt_sofskip
  1443.     sub.l    d0,Voice.LENGTH(A4)
  1444.     add.l    d0,Voice.START(A4)
  1445.     move.l    Voice.START(A4),Mixer.START(A5)    ;Set sampledata pointer
  1446.     move.l    Voice.LENGTH(A4),Mixer.LENGTH(A5)    ;Set length
  1447.     rts
  1448. pt_sofskip
  1449.     move.l    #1,Voice.LENGTH(A4)        ;plus de sample?
  1450.     move.l    Voice.LENGTH(A4),Mixer.LENGTH(A5)    ;Set length
  1451.     rts
  1452.  
  1453. pt_volumeslide
  1454.     move.w    Voice.COMMANDPARS(a4),D0
  1455. vol_slide_return
  1456.     move    Voice.VOLUME(a4),d1
  1457.     add    d0,d1
  1458.     bge.s    .vol_noneg
  1459.     clr    d1
  1460. .vol_noneg
  1461.     cmpi.w    #$4000,d1
  1462.     ble.s    .vol_nohi
  1463.     move.w    #$4000,d1
  1464. .vol_nohi
  1465.     move.w    d1,Voice.VOLUME(a4)
  1466.     lsr.w    #8,d1
  1467.     move.w    d1,Mixer.VOLUME(a5)
  1468.     rts
  1469.  
  1470. pt_positionjump    
  1471.     move.w    Voice.COMMANDPARS(A4),D0
  1472.     subq.w    #1,d0
  1473.     move.w    d0,EarxPlay.position
  1474.     move.w    #-1,EarxPlay.pattpos
  1475.     rts
  1476.  
  1477. pt_volumechange
  1478.     move.w    Voice.COMMANDPARS(a4),d0
  1479.     lsl.w    #8,d0
  1480.     move.w    d0,Voice.VOLUME(a4)
  1481.     rts
  1482.  
  1483. pt_patternbreak:
  1484.     addq.w    #1,EarxPlay.position
  1485.     move.w    Voice.COMMANDPARS(a4),d0
  1486.     subq.w    #1,d0
  1487.     move.w    d0,EarxPlay.pattpos
  1488.     rts
  1489.  
  1490. pt_filteronoff    
  1491. ;    synchro ..
  1492. ;    st    filter    
  1493.     rts
  1494.  
  1495. pt_setspeed:    
  1496.     move.w    Voice.COMMANDPARS(a4),d0
  1497.     beq.s    .speed_nul
  1498.     movea.l    EarxPlay.modAdr,a0
  1499. ; We assume ciaa mode here..
  1500.     cmpi.b    #$20,d0
  1501.     bhs.s    set_tempo
  1502. .no_ciaamode:
  1503.     move.w    d0,EarxPlay.counter
  1504.     move.w    d0,EarxPlay.speed
  1505. .speed_nul:
  1506.     rts
  1507.  
  1508. set_tempo:
  1509.     clr.l    d1
  1510.     move.b    d0,d1
  1511.     move.w    (EarxPlay.timerTable.l,d1.l*2),d0
  1512.     move.b    d0,EarxPlay.timerCount
  1513.     move.b    d0,EarxPlay.timerBase
  1514.     lsr.w    #8,d0
  1515.     clr.b    $fffffa19.w            ; Stop timer a.
  1516.     move.b    d0,$fffffa1f.w
  1517.     move.b    #$7,$fffffa19.w            ; prediv = 200
  1518.     rts
  1519.  
  1520. pt_fineportaup    
  1521. pt_portaup
  1522.     move    Voice.NPERIOD(a4),d0
  1523.     sub    Voice.COMMANDPARS(a4),d0
  1524.     cmp    #$71,d0
  1525.     bge.s    .no_lower_per
  1526.     move    #$71,d0
  1527. .no_lower_per
  1528.     move    d0,Voice.NPERIOD(a4)
  1529.     move    d0,Mixer.PERIOD(a5)
  1530.     rts
  1531.  
  1532. pt_fineportadown    
  1533. pt_portadown
  1534.     move    Voice.NPERIOD(a4),d0
  1535.     add    Voice.COMMANDPARS(a4),d0
  1536.     cmp    #$358,d0
  1537.     bmi.s    .no_lower_per
  1538.     move    #$358,d0
  1539. .no_lower_per
  1540.     move    d0,Voice.NPERIOD(a4)
  1541.     move    d0,Mixer.PERIOD(a5)
  1542.     rts
  1543.  
  1544. pt_setglisscontrol    
  1545.     move.b    Voice.COMMANDPARS+1(a4),Voice.GLISSFUNK+1(a4)    
  1546.     rts
  1547.  
  1548. pt_setvibratocontrol    
  1549.     move.b    Voice.COMMANDPARS+1(a4),Voice.WAVECONTROL+1(a4)    
  1550.     rts
  1551.  
  1552. pt_setfinetune    
  1553.     move.b    Voice.COMMANDPARS+1(a4),Voice.FINETUNE(a4)
  1554.     rts
  1555.  
  1556. pt_jumploop    
  1557.     move    Voice.COMMANDPARS(a4),d0
  1558.     beq.s    pt_setloop
  1559.     tst.w    Voice.LOOPCOUNT(A4)
  1560.     beq.s    pt_jumpcnt
  1561.     subq    #1,Voice.LOOPCOUNT(A4)
  1562.     beq.s    return_pt
  1563. pt_jmploop
  1564.     move.w    Voice.PATTPOS(a4),EarxPlay.breakPos
  1565.     st    EarxPlay.pbreak
  1566.     rts
  1567. pt_jumpcnt
  1568.     move.w    d0,Voice.LOOPCOUNT(A4)
  1569.     move.w    Voice.PATTPOS(a4),EarxPlay.breakPos
  1570.     st    EarxPlay.pbreak
  1571.     rts
  1572. pt_setloop
  1573.     move.w    EarxPlay.pattpos,Voice.PATTPOS(a4)
  1574. return_pt
  1575.     rts
  1576.  
  1577. pt_settremolocontrol    
  1578.     move.b    Voice.COMMANDPARS+1(a4),Voice.WAVECONTROL(a4)
  1579.     rts
  1580.  
  1581. pt_karplusstrong    
  1582.     move.l    Voice.LOOPSTART(a4),a0
  1583.     move.l    a0,a1
  1584.     btst    #0,Voice.SINFO(a4)
  1585.     bne.s    .sample_16bits
  1586.     move.l    Voice.REPLEN(a4),d0
  1587.     move.b    (a0),d1
  1588. .pt_karplop
  1589.     ext    d1
  1590.     move.b    1(a0),d2
  1591.     ext    d2
  1592.     add    d2,d1
  1593.     asr    d1
  1594.     move.b    d1,(a0)+
  1595.     exg    d2,d1
  1596.     subq.l    #1,d0
  1597.     bne.s    .pt_karplop
  1598.     move.b    (a1),d2
  1599.     ext    d2
  1600.     add    d1,d2
  1601.     asr    d2
  1602.     move.b    d2,(a0)
  1603.     rts
  1604.  
  1605. .sample_16bits
  1606.     move    Voice.REPLEN(a4),d0
  1607.     lsr    d0
  1608.     move.w    (a0),d1
  1609. .pt_karplop2
  1610.     ext.l    d1
  1611.     move.w    2(a0),d2
  1612.     ext.l    d2
  1613.     add.l    d2,d1
  1614.     asr.l    d1
  1615.     move.w    d1,(a0)+
  1616.     exg    d2,d1
  1617.     subq.l    #1,d0
  1618.     bne.s    .pt_karplop2
  1619.     move.w    (a1),d2
  1620.     ext.l    d2
  1621.     add.l    d1,d2
  1622.     asr.l    d2
  1623.     move.w    d2,(a0)
  1624.     rts
  1625.  
  1626. pt_retrignote:
  1627.     move.w    Voice.COMMANDPARS(A4),D0
  1628.     beq.s    .end
  1629.     clr.l    d1
  1630.     move.w    EarxPlay.counter,D1
  1631.     bne.s    .skip
  1632.     tst.w    Voice.IPERIOD(A4)
  1633.     bne.s    .end
  1634. .skip:    divu.w    D0,D1
  1635.     swap    d1
  1636.     tst.w    d1
  1637.     bne.s    .end
  1638.     MOVE.L    Voice.START(A4),Mixer.START(A5)        ;Set sampledata pointer
  1639.     MOVE.l    Voice.LENGTH(A4),Mixer.LENGTH(A5)    ;Set length
  1640.     MOVE.w    Voice.NPERIOD(A4),Mixer.PERIOD(A5)
  1641.     MOVE.L    Voice.LOOPSTART(A4),Mixer.LOOPSTART(A5)
  1642.     MOVE.L    Voice.REPLEN(A4),Mixer.LOOPLENGTH(A5)
  1643.     clr.b    Mixer.INFO(a5)                ; Tell mixer to start sample again.
  1644. .end:    rts
  1645.  
  1646. pt_volumefineup    
  1647. pt_volumefinedown    
  1648.     move.w    Voice.COMMANDPARS(a4),D0
  1649.     bra    vol_slide_return
  1650.     rts
  1651.  
  1652. pt_notecut    
  1653.     move.w    Voice.COMMANDPARS(a4),D0
  1654.     cmp.w    EarxPlay.counter,D0
  1655.     bne.s    .return
  1656.     clr.w    Voice.VOLUME(A4)
  1657. .return
  1658.     rts
  1659.  
  1660. pt_notedelay    
  1661.     move.w    Voice.COMMANDPARS(a4),d0
  1662.     cmp.w    EarxPlay.counter,D0
  1663.     bne.s    .return
  1664.     move    Voice.NPERIOD(a4),d0
  1665.     beq.s    .return
  1666.     move.b    #$fe,Mixer.FLAGINFO(a5)    ;s_ptr_sample(a5)=s_loopstart(a5)    
  1667.     move.L    Voice.START(A4),Mixer.START(A5)    ;Set sampledata pointer
  1668.     move.l    Voice.LENGTH(A4),Mixer.LENGTH(A5)    ;Set length
  1669.     move.w    d0,Mixer.PERIOD(A5)
  1670.     move.L    Voice.LOOPSTART(A4),Mixer.LOOPSTART(A5)
  1671.     move.L    Voice.REPLEN(A4),Mixer.LOOPLENGTH(A5)
  1672. .return
  1673.     rts
  1674.  
  1675. pt_patterndelay    
  1676.     move.w    Voice.COMMANDPARS(A4),D0
  1677.     tst.w    EarxPlay.pattDelayTime2
  1678.     bne.s    .return
  1679.     addq.w    #1,d0
  1680.     move.w    d0,EarxPlay.pattDelayTime
  1681. .return:rts
  1682.  
  1683. pt_funkit    
  1684.     move.b    Voice.COMMANDPARS(a4),d0
  1685.     move.b    d0,Voice.GLISSFUNK(a4)
  1686.     tst.w    Voice.GLISSFUNK(a4)
  1687.     beq.s    pt_funkend
  1688.  
  1689. EarxPlay.updateFunk:
  1690.     move.b    Voice.GLISSFUNK(a4),D0
  1691.     beq.s    pt_funkend
  1692.     lea    pt_funktable(PC),a2
  1693.     move.b    (a2,d0.w),d0
  1694.     add.b    d0,Voice.FUNKOFFSET(a4)
  1695.     btst    #7,Voice.FUNKOFFSET(a4)
  1696.     beq.s    pt_funkend
  1697.     clr.b    Voice.FUNKOFFSET(a4)
  1698.     move.l    Voice.LOOPSTART(a4),D0
  1699.     move.l    Voice.REPLEN(a4),D1
  1700.     add.l    d1,d0
  1701.     add.l    d1,d0
  1702.     move.l    Voice.WAVESTART(a4),a2
  1703.     addq.l    #1,a2
  1704.     cmp.l    d0,a2
  1705.     blo.s    .pt_funkok
  1706.     move.l    Voice.LOOPSTART(a4),a2
  1707. .pt_funkok
  1708.     move.l    a2,Voice.WAVESTART(a4)    ;sert a quoi?
  1709.     not.b    (a2)
  1710. pt_funkend:
  1711.     rts
  1712.  
  1713.  
  1714. ;= mixer ===================================================================
  1715. ;
  1716. ; Mixes and resamples the stuff given by Mixer.table.
  1717. ; Uses the dsp mixer remake by earx.
  1718. ;
  1719.  
  1720. EarxPlay.mix:
  1721.     lea    DSP_BASE+2.w,a5            ; a5: host status reg
  1722.     lea    4(a5),a3            ; a3: host tx/rx (lower word)
  1723.     save_host
  1724.     WritHost    #$1            ; Tell dsp, mixing is still active..
  1725.     move.l    #$0003FFFF,d3            ; d3.l=global vol
  1726.     clr.w    Mixer.firstl
  1727.     lea    Mixer.lrTable,a1
  1728.     lea    Mixer.table,a4
  1729.     move.w    EarxPlay.numTracks,d7        ; d7.w>=4
  1730.     divu.w    d7,d3                ; d3.w= vol per channel
  1731.     subq.w    #1,d7
  1732.  
  1733. .voice_loop:
  1734.     clr.l    d0
  1735.     move.b    (a1)+,d0            ; d0.b=chn info
  1736.     pea    (a1)
  1737.  
  1738. ; If voice is mute, don't mix!
  1739.     cmpi.b    #$FD,Mixer.INFO(a4)
  1740.     beq    .next_track
  1741.     move.w    Mixer.VOLUME(a4),d1
  1742.     beq    .next_track
  1743. ;    tst.w    Mixer.PERIOD(a4)
  1744. ;    beq    .next_track
  1745.  
  1746. ; Check channel and if you can move instead of add..
  1747.     tst.b    d0
  1748.     bmi    .next_track
  1749.     bne.s    .right_voice
  1750. .left_voice
  1751.     tst.b    Mixer.firstl
  1752.     bne.s    .add_voice
  1753.     st    Mixer.firstl
  1754.     bra.s    .move_voice
  1755. .right_voice
  1756.     tst.b    Mixer.firstr
  1757.     bne.s    .add_voice
  1758.     st    Mixer.firstr
  1759. .move_voice:
  1760.     addq.w    #%010,d0
  1761. .add_voice:
  1762.  
  1763. ; bit 0: 0=l, 1=r; bit 1: 0=add, 1=move; bit 2: 1=play special spl
  1764.     WritHost    d0
  1765.  
  1766. ; Send trackvolume.
  1767. ; d1.w=spl volume, d3.w=channel volume
  1768.     mulu.w    d3,d1
  1769.     WritHost    d1
  1770.  
  1771. ; Send frequency, get blocklength
  1772.     move.w    Mixer.PERIOD(a4),d1
  1773.     move.l    (freq_table.l,d1.w*4),d1
  1774.     WritHost    d1            ; Send frequency.
  1775.     ReadHost    d0            ; d0.l=bytes to send (blocksize)
  1776.     beq    .next_track
  1777.  
  1778.     move.l    d0,.blocksize
  1779.  
  1780. ; Start sample, if not already started.
  1781.     tst.b    Mixer.INFO(a4)
  1782.     bne.s    .sample_started
  1783.     move.l    Mixer.START(a4),Mixer.SAMPLEADR(a4)
  1784.     st    Mixer.INFO(a4)
  1785. .sample_started:
  1786.  
  1787. ; d0.l=blocksize
  1788. ; Set defaults for no-wrap situation.
  1789.     move.l    d0,.head
  1790.     clr.w    .nr_loops
  1791.     clr.l    .tail
  1792.  
  1793. ; Test for wrapping..
  1794. ; Split the block up in head, body (loops) and tail parts..
  1795.     move.l    Mixer.SAMPLEADR(a4),d1
  1796.     movea.l    d1,a1                ; a1: actual pos
  1797.     add.l    d0,d1                ; d1.l: unwrapped next pos
  1798.     cmpi.b    #$FE,Mixer.INFO(a4)
  1799.     beq.s    .handle_loop
  1800.  
  1801. .handle_whole_play:
  1802.     move.l    Mixer.START(a4),d2
  1803.     add.l    Mixer.LENGTH(a4),d2        ; d2.l: sample_end
  1804.     cmp.l    d2,d1
  1805.     ble.s    .admin_done            ; If not wrapped, don't split up.
  1806. ; This frame contains a possible loop.. Check if it has one..
  1807.     cmpi.l    #2,Mixer.LOOPLENGTH(a4)
  1808.     bhi.s    .looplength_okay
  1809.     move.b    #$FD,Mixer.INFO(a4)        ; Indicate mute.
  1810.     bra.s    .looplength_checked
  1811. .looplength_okay:
  1812.     move.b    #$FE,Mixer.INFO(a4)        ; Indicate loop.
  1813. .looplength_checked:
  1814.     sub.l    d2,d1                ; d1.l=loops+tail
  1815. .calc_h_l_t:
  1816.     move.l    d0,d2                ; d2.l=blocksize=head+loops+tail
  1817.     sub.l    d1,d2                ; d2.l=head
  1818.     move.l    d2,.head            ; Store headsize.
  1819.     clr.l    d2
  1820.     divu.l    Mixer.LOOPLENGTH(a4),d2:d1
  1821.     move.w    d1,.nr_loops            ; Store #loops.
  1822.     move.l    d2,.tail            ; Store tailsize.
  1823.     add.l    Mixer.LOOPSTART(a4),d2
  1824.     move.l    d2,d1                ; d1.l= next pos.
  1825.     bra.s    .admin_done
  1826.  
  1827. .handle_loop:
  1828.     move.l    Mixer.LOOPSTART(a4),d2
  1829.     add.l    Mixer.LOOPLENGTH(a4),d2        ; d2.l: loop_end
  1830.     cmp.l    d2,d1
  1831.     ble.s    .admin_done
  1832.     sub.l    d2,d1                ; d1.l=loops+tail
  1833.     bra.s    .calc_h_l_t
  1834.  
  1835. .admin_done:
  1836.     move.l    d1,Mixer.SAMPLEADR(a4)        ; Store next pos.
  1837.  
  1838. ; Write the block (head, loops, tail)..
  1839. ; Warning: this sends (blocksize/2 + 1) words!
  1840. ; (plus a parity byte if required)
  1841. ; a1: actual pos
  1842.  
  1843. ; Give packet info to dsp..
  1844.     move.l    a1,d1                ; d1.l: actual pos
  1845.     env    (a5)
  1846.     move.w    d1,(a3)                ; Transfer start to let dsp see parity..
  1847.  
  1848. ; Send definitive size to dsp..
  1849.     move.l    .blocksize(pc),d0
  1850.     cmpi.b    #$FD,Mixer.INFO(a4)        ; Mute? -> only send head.
  1851.     bne.s    .size_found
  1852.     move.l    .head(pc),d0
  1853.     clr.w    .nr_loops
  1854.     clr.l    .tail
  1855. .size_found:
  1856.     move.l    d0,d5
  1857.     andi.w    #$FFFE,d5
  1858.     addq.l    #2,d5                ; (bytes/2)+1 = exact amount of words to send to dsp
  1859.     lsr.l    d0                ; d0.w=n-1=#words to send-1
  1860.     WritHost    d0
  1861.     tst.l    d0
  1862.     beq    .next_track
  1863.     lsr.l    d1                ; Shift out lsb of sampleadr.
  1864.     bcc.s    .even                ; Dsp also tests parity!
  1865.     clr.l    d1
  1866.     move.b    (a1)+,d1
  1867.     swap    d1
  1868.     WritHost    d1            ; Send odd sample.
  1869. .even:    env    (a5)
  1870.     
  1871. ; head..
  1872.     move.l    .head(pc),d0
  1873.     bsr    .send_block
  1874.  
  1875. ; body..
  1876.     move.w    .nr_loops(pc),d6
  1877.     beq.s    .body_done
  1878.     move.l    Mixer.LOOPLENGTH(a4),d1
  1879.     movea.l    Mixer.LOOPSTART(a4),a2
  1880.     lsr.l    d1
  1881.     move.l    d1,d0
  1882.     mulu.w    d6,d0
  1883.     sub.l    d0,d5
  1884.     sub.l    d0,d5
  1885.     subq.w    #1,d6
  1886.     subq.w    #1,d1
  1887.  
  1888. .body_loop:
  1889.     move.w    d1,d0
  1890.     movea.l    a2,a1
  1891. ; Send d0.w+1 words!
  1892. .slloop:move.w    (a1)+,(a3)
  1893.     dbf    d0,.slloop
  1894.     dbf    d6,.body_loop
  1895. .body_done:
  1896.  
  1897. ; tail..
  1898.     move.l    .tail(pc),d0
  1899.     move.l    d0,d1
  1900.     lsr.l    d1
  1901.     beq.s    .tail_done
  1902.     movea.l    Mixer.LOOPSTART(a4),a1
  1903. .tail_size_calced:
  1904.     bsr    .send_block
  1905. .tail_done:
  1906.  
  1907. ; Check for last word(s)...
  1908.     tst.l    d5
  1909.     beq.s    .next_track
  1910.     move.l    Mixer.START(a4),d6
  1911.     add.l    Mixer.LENGTH(a4),d6        ; d6.l: sample_end
  1912.  
  1913. .rest_loop:
  1914.     move.l    Mixer.LOOPLENGTH(a4),d2
  1915.     cmpi.l    #2,d2
  1916.     ble.s    .correct_addy            ; No loop? -> Don't wrap addy.
  1917.     move.l    Mixer.LOOPSTART(a4),d1
  1918.     move.l    d1,d0
  1919.     add.l    d2,d0                ; d0.l: loopend
  1920.     cmp.l    a1,d0                ; Looping sample exceeding loop?
  1921.     bhi.s    .correct_addy
  1922.     movea.l    d1,a1
  1923. .correct_addy:
  1924.     cmpa.l    d6,a1                ; If sample exceeds end, then put some void to the dsp.
  1925.     blt.s    .in_sample
  1926.     lea    .void(pc),a1
  1927. .in_sample:
  1928.     move.w    (a1)+,(a3)
  1929.     subq.l    #2,d5
  1930.     bne.s    .rest_loop
  1931.  
  1932. .next_track:
  1933.     movea.l    (sp)+,a1
  1934.     adda.w    #Mixer.SIZE,a4
  1935.     dbf    d7,.voice_loop
  1936.  
  1937.     WritHost    #$1234            ; Send terminator.
  1938.     restore_host
  1939.     rts
  1940.  
  1941. ; This sends a loop or tail to host.
  1942. ; remember, loopstart and tailstart are even and looplen>=2!
  1943. ; send d0/2 words!
  1944. .send_block:
  1945.     lsr.l    d0                ; d0.w=n=#words to send
  1946.     sub.l    d0,d5
  1947.     sub.l    d0,d5
  1948.     move.l    d0,d1
  1949.     beq.s    .sent
  1950.     lsr.w    #4,d0
  1951.     andi.w    #$F,d1
  1952.     neg.l    d1
  1953.     jmp    .jump(pc,d1.l*2)
  1954.     
  1955. ; Send d0.w words!
  1956. .sendlloop:
  1957.     REPT    16
  1958.     move.w    (a1)+,(a3)
  1959.     ENDR
  1960. .jump:    dbf    d0,.sendlloop
  1961.  
  1962. .sent:    rts
  1963.  
  1964. .blocksize:
  1965.     ds.l    1
  1966. .head:    ds.l    1                ; 
  1967. .tail:    ds.l    1
  1968. .nr_loops:
  1969.     ds.w    1
  1970. .void:    ds.l    1
  1971.  
  1972. ;= data ====================================================================
  1973.  
  1974. ; frequency information
  1975. table_frq:
  1976.     dc.l    $24063686,$3639d737
  1977.  
  1978. ; mixing tables
  1979. Mixer.lrTable:
  1980.     REPT    EarxPlay.MAX_TRACKS/2
  1981.     DC.B    0,1
  1982.     ENDR
  1983.  
  1984. ; dsp mixer
  1985. EarxPlay.mixer:
  1986.     INCBIN    RSNDEARX.P56
  1987. EarxPlay.mixerEnd:
  1988.     EVEN
  1989.  
  1990. ;= reserves ================================================================
  1991.  
  1992.     bss
  1993.  
  1994. ; player status
  1995. EarxPlay.initialized:
  1996.     ds.w    1
  1997.  
  1998. ; module information
  1999. EarxPlay.modAdr:
  2000.     ds.l    1
  2001. EarxPlay.splAdrTable:                ; addresses of samples
  2002.     ds.l    31
  2003. EarxPlay.numTracks:
  2004.     ds.w    1
  2005.  
  2006. ; player parameters
  2007. EarxPlay.playing:
  2008.     ds.w    1
  2009. EarxPlay.position:                ; current position in mod
  2010.     ds.w    1
  2011. EarxPlay.speed:                    ; #vbl's per note
  2012.     ds.w    1
  2013. EarxPlay.counter:                ; #vbl's to go till next note
  2014.     ds.w    1
  2015. EarxPlay.breakPos:
  2016.     ds.w    1
  2017. EarxPlay.pattpos:                ; current position in pattern
  2018.     ds.w    1
  2019. EarxPlay.pbreak:
  2020.     ds.w    1
  2021. EarxPlay.pattDelayTime:
  2022.     ds.w    1
  2023. EarxPlay.pattDelayTime2:
  2024.     ds.w    1
  2025.  
  2026. ; synchronisation command info
  2027. command_buffer:
  2028.     ds.b    32
  2029. command_tail:
  2030.     ds.w    1
  2031. command_head:
  2032.     ds.w    1
  2033.  
  2034. ; frequency information
  2035. EarxPlay.timerBase:                ; #timerticks in a 'vbl'
  2036.     ds.b    1
  2037. EarxPlay.timerCount:                ; #timerticks till next 'vbl'
  2038.     ds.b    1
  2039. matr_i:    ds.w    1
  2040. freq_table:
  2041.     ds.l     80+900
  2042. EarxPlay.timerTable:
  2043.     ds.w    256
  2044.  
  2045. ; note structures
  2046. Voice.table:
  2047.     DS.B    EarxPlay.MAX_TRACKS*Voice.SIZE
  2048.  
  2049. ; mixing tables
  2050. Mixer.table:
  2051.     DS.B    EarxPlay.MAX_TRACKS*Mixer.SIZE    ; spl offset, loop, start, vol, freq info for all tracks
  2052. Mixer.firstl:
  2053.     DS.B    1                ; indicates 1st left track
  2054. Mixer.firstr:
  2055.     DS.B    1                ; indicates 1st right track
  2056.  
  2057. ; mfp context
  2058. mfp_save:
  2059.     ds.l    20
  2060.