home *** CD-ROM | disk | FTP | other *** search
/ Sound, Music & MIDI Collection 2 / SMMVOL2.bin / DOS / SS_PLAY / FUNK106.ZIP / FUNK_S.ZIP / MOD2FNK.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-03-31  |  21.2 KB  |  799 lines

  1. {
  2. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. ;                                                                          ;
  4. ; MOD2FNK:-                                                                ;
  5. ;                                                                          ;
  6. ; Converts "M.K." Modules to the FunkTracker format (11/03/95)             ;
  7. ;                                                                          ;
  8. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  9. }
  10. {$I-}
  11. program mod2fnk;
  12.  
  13. const
  14.   version          = 'V1.2';
  15.   tmodsamples_size = 30;
  16.   fnbuf_size       = 20000;
  17.  
  18. type
  19.   t_mod_type = (NO_MOD, FOURCHAN_MOD, EIGHTCHAN_MOD);
  20. {=MOD STRUCTURES==============================}
  21.   tmodsamples = record
  22.     sname             : array[1..22] of char;
  23.     slength           : word;
  24.     sfinetune         : byte;
  25.     svolume           : byte;
  26.     srepeat           : word;
  27.     sreplen           : word;
  28.   end;
  29.  
  30.   tmodheader = record
  31.     songname          : array[1..20] of char;
  32.     samples           : array[1..31] of tmodsamples;
  33.     songlen           : byte;
  34.     restart           : byte;
  35.     sequences         : array[1..128] of byte;
  36.     mk                : array[1..4] of char;
  37.   end;
  38.  
  39.   tmodslot = record
  40.     byte1             : byte;
  41.     byte2             : byte;
  42.     byte3             : byte;
  43.     byte4             : byte;
  44.   end;
  45.  
  46. {=FNK STRUCTURES==============================
  47. ─'info' code──────────────────────────────────┴────────────────────────
  48. 0 0 0 0 0 0 0 0   1 1 1 1 1 1 1 1   2 2 2 2 2 2 2 2   3 3 3 3 3 3 3 3
  49. \-day---/ \month--/ \----year---/   \-card/ \-CPU-/   | 0 0 0 0 0 0 0
  50.                                                       | \memory reqi/
  51.                                                       |    (256Kb x)
  52.                                        16 bit = 1 ----
  53. cpu:  0 = Unknown
  54.       1 = IBM ????
  55.       2 = IBM ????
  56.       3 = Intel386
  57.       4 = Intel486
  58.       5 = Pentium
  59. card:
  60.       0 = SB 2.0
  61.       1 = SB PRO
  62.       2 = GUS v<>
  63.       3 = Bogus SB
  64.       4 = Reserved
  65.       5 = GUS f<>
  66.       6 = Ripped/converted from another format
  67. }
  68.  
  69.   tfnksamples = record
  70.     sname             : array [1..19] of char;
  71.     start             : longint;
  72.     length            : longint;
  73.     volume            : byte;
  74.     balance           : byte;
  75.     pt_and_sop        : byte;
  76.     vv_waveform       : byte;
  77.     rl_and_as         : byte;
  78.   end;
  79.  
  80.   tfnkheader = record
  81.     sig               : array[1..4] of char;
  82.     info              : array[1..4] of byte;
  83.     LZH_check_size    : longint;
  84.     LZH_check_sum     : longint;
  85.     loop_order        : byte;
  86.     order_list        : array[1..256] of byte;
  87.     break_list        : array[1..128] of byte;
  88.     samples           : array[1..64] of tfnksamples;
  89.   end;
  90.  
  91.   tfnkslot = record
  92.     byte1             : byte;
  93.     byte2             : byte;
  94.     byte3             : byte;
  95.   end;
  96.  
  97. {=============================================}
  98.  
  99. var
  100.   newstr              : string[80];
  101.   modfile             : file;
  102.   funkfile            : file;
  103.   modheader           : tmodheader;
  104.   fnkheader           : tfnkheader;
  105.   numpatterns         : byte;
  106.   numsamples          : byte;
  107.   rws                 : word;
  108.   modpattern          : array[0..(64*8)-1] of tmodslot;
  109.   fnkpattern          : array[0..(64*8)-1] of tfnkslot;
  110.   trans_buffer1       : array[0..(fnbuf_size-1)] of byte;
  111.   trans_buffer2       : array[0..(fnbuf_size-1)] of byte;
  112.  
  113.   channels            : byte;
  114.   pattern             : byte;
  115.   treks               : byte;
  116.   oldsample           : array[0..7] of byte;
  117.   mod_type            : t_mod_type;
  118.  
  119. {
  120. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  121. ;                                                                          ;
  122. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  123. }
  124. function convert_header : boolean;
  125. var
  126.   y, m, d, dow : Word;
  127.   x            : byte;
  128. begin
  129.   convert_header := false;
  130. {init fnk header}
  131.   fnkheader.sig[1] := 'F';
  132.   fnkheader.sig[2] := 'u';
  133.   fnkheader.sig[3] := 'n';
  134.   fnkheader.sig[4] := 'k';
  135.   asm
  136.     mov    ah,2ah
  137.     int    21h
  138.     xor    ax,ax
  139.     mov    al,dl
  140.     xor    dl,dl
  141.     xchg   dl,dh
  142.     shl    dx,5
  143.     or     ax,dx
  144.     sub    cx,1980
  145.     shl    cx,9
  146.     or     ax,cx
  147.     mov    word[fnkheader.info+0],ax
  148.     xor    ax,ax
  149.     mov    al,6    {card_type}
  150.     mov    bl,1    {cpu type}
  151.     shl    bl,4
  152.     or     al,bl
  153.     mov    word[fnkheader.info+2],ax
  154.   end;
  155.   fnkheader.loop_order := $FF;
  156.   for dow := 1 to 256 do
  157.   begin
  158.     fnkheader.order_list[dow] := $ff;
  159.   end;
  160.   for dow := 1 to 128 do
  161.   begin
  162.     fnkheader.break_list[dow] := $3f;
  163.   end;
  164.   for dow := 1 to 64 do
  165.   begin
  166.     for y := 1 to 19 do
  167.     begin
  168.       fnkheader.samples[dow].sname[y] := #0;
  169.     end;
  170.     fnkheader.samples[dow].start := $ffffffff;
  171.     fnkheader.samples[dow].length := 0;
  172.     fnkheader.samples[dow].volume := $ff;
  173.     fnkheader.samples[dow].balance := $80;
  174.     fnkheader.samples[dow].pt_and_sop := $08;
  175.     fnkheader.samples[dow].vv_waveform := $0;
  176.     fnkheader.samples[dow].rl_and_as := $43;
  177.   end;
  178.  
  179. {convert header}
  180.   mod_type := NO_MOD;
  181.   blockread(modfile, modheader, sizeof(modheader), rws);
  182.   if (modheader.mk[1] = 'M') and
  183.      (modheader.mk[2] = '.') and
  184.      (modheader.mk[3] = 'K') and
  185.      (modheader.mk[4] = '.') then
  186.   begin
  187.     mod_type := FOURCHAN_MOD;
  188.     writeln('converting 4 channel M.K...');
  189.   end
  190.   else
  191.   begin
  192.     if (modheader.mk[1] = '8') and
  193.        (modheader.mk[2] = 'C') and
  194.        (modheader.mk[3] = 'H') and
  195.        (modheader.mk[4] = 'N') then
  196.     begin
  197.       mod_type := EIGHTCHAN_MOD;
  198.       writeln('converting 8 channel 8CHN...');
  199.     end
  200.     else
  201.     begin
  202.       writeln('Not an regonised MOD module.');
  203.     end;
  204.   end;
  205.  
  206.   if mod_type <> NO_MOD then
  207.   begin
  208.     convert_header := true;
  209.     for y := 1 to 128 do
  210.     begin
  211.       fnkheader.order_list[y] := modheader.sequences[y];
  212.     end;
  213.     for y := 1 to 31 do
  214.     begin
  215.       for dow := 1 to 19 do
  216.       begin
  217.         fnkheader.samples[y].sname[dow] := modheader.samples[y].sname[dow];
  218.       end;
  219.       asm
  220.         mov    al,tmodsamples_size
  221.         mov    bl,byte [y]
  222.         dec    bl
  223.         mul    bl
  224.         mov    bx,ax
  225.         add    bx,offset modheader.samples
  226.  
  227.         mov    ax,word[bx+tmodsamples.slength]
  228.         xchg   al,ah
  229.         shl    ax,1
  230.         mov    word[bx+tmodsamples.slength],ax
  231.  
  232.         mov    ax,word[bx+tmodsamples.srepeat]
  233.         xchg   al,ah
  234.         shl    ax,1
  235.         mov    word[bx+tmodsamples.srepeat],ax
  236.  
  237.         mov    ax,word[bx+tmodsamples.sreplen]
  238.         xchg   al,ah
  239.         shl    ax,1
  240.         mov    word[bx+tmodsamples.sreplen],ax
  241.       end;
  242.  
  243.       if modheader.samples[y].slength > 0 then
  244.       begin
  245.         if modheader.samples[y].sreplen > 2 then
  246.         begin
  247.           fnkheader.samples[y].length := modheader.samples[y].srepeat +
  248.                                          modheader.samples[y].sreplen;
  249.           if fnkheader.samples[y].length > modheader.samples[y].slength then
  250.           begin
  251.             fnkheader.samples[y].length := modheader.samples[y].slength;
  252.           end;
  253.           fnkheader.samples[y].start := modheader.samples[y].srepeat;
  254.         end
  255.         else
  256.         begin
  257.           fnkheader.samples[y].length := modheader.samples[y].slength;
  258.         end;
  259.  
  260.         if modheader.samples[y].svolume > 0 then
  261.         begin
  262.           dow := trunc((modheader.samples[y].svolume * 256) / 64);
  263.           if dow = 256 then
  264.           begin
  265.             dow := 255;
  266.           end;
  267.           fnkheader.samples[y].volume := byte(dow);
  268.         end
  269.         else
  270.         begin
  271.           fnkheader.samples[y].volume := 0;
  272.         end;
  273.       end;
  274.     end;
  275.     blockwrite(funkfile, fnkheader, sizeof(fnkheader), rws);
  276.   end;
  277. end;
  278.  
  279. {
  280. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  281. ;                                                                          ;
  282. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  283. }
  284. const
  285.   mus_match : array[0..60] of word = (
  286.     1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,912,
  287.     856,808,762,720,678,640,604,570,538,508,480,453,
  288.     428,404,381,360,339,320,302,285,269,254,240,226,
  289.     214,202,190,180,170,160,151,143,135,127,120,113,
  290.     107,101,95,90,85,80,75,71,67,63,60,56,0
  291.   );
  292.  
  293. function mod_notematcher(note : word) : byte;
  294. var
  295.   x     : byte;
  296.   label exit;
  297. begin
  298.   mod_notematcher := 0;
  299.   for x := 0 to 60 do
  300.   begin
  301.     if note >= mus_match[x] then
  302.     begin
  303.       mod_notematcher := x;
  304.       goto exit;
  305.     end;
  306.   end;
  307. exit:
  308. end;
  309.  
  310. {
  311. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  312. ;                                                                          ;
  313. ;-MOD SLOT FORMAT----------------------------------------------------------;
  314. ;                                                                          ;
  315. ; _____byte 1_____   byte2_    _____byte 3_____   byte4_                   ;
  316. ;/                ╓ /      ╓  /                ╓ /      ╓                  ;
  317. ;0000          0000-00000000  0000          0000-00000000                  ;
  318. ;                                                                          ;
  319. ;upper four    12 bits for    lower four    effect command.                ;
  320. ;bits of sam-  note period.   bits of sam-                                 ;
  321. ;ple number.                  ple number.                                  ;
  322. ;
  323. ;-FUNK SLOT FORMAT---------------------------------------------------------
  324. ;
  325. ;Each pattern block is 600h bytes - 8 by 64 slot. Each slot has
  326. ;the following format:
  327. ;
  328. ; 00000000 11111111 22222222
  329. ; \____/\_____/\__/ \______/
  330. ;  Note  Sample com  command value
  331. ;
  332. ; - if note   = 3D, reload sample attr
  333. ; - if note   = 3F, then it's a null slot
  334. ; - if note   = 3E, then sample only slot
  335. ;
  336. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  337. }
  338. procedure convert_command(var modcom, modcomv, fnkcom, fnkcomv : byte);
  339. var
  340.   xxx : word;
  341. procedure convert_slide;
  342. begin      { 0 = slide down}
  343.   if (modcomv and $f0) <> 0 then
  344.   begin
  345.     fnkcom := byte('G');
  346.     fnkcomv := modcomv and $f;
  347.   end
  348.   else
  349.   begin
  350.     fnkcom := byte('H');
  351.     fnkcomv := modcomv and $f;
  352.   end;
  353. end;
  354.  
  355. begin
  356.   fnkcom := $f + byte('A');
  357.   fnkcomv := 0;
  358.   case modcom of
  359.     0: {arpeggio}
  360.     begin
  361.       fnkcom := byte('L');
  362.       fnkcomv := modcomv;
  363.     end;
  364.     1: {portup}
  365.     begin
  366.       fnkcom := byte('A');
  367.       fnkcomv := modcomv;
  368.     end;
  369.     2: {portdn}
  370.     begin
  371.       fnkcom := byte('B');
  372.       fnkcomv := modcomv;
  373.     end;
  374.     3: {porta note}
  375.     begin
  376.       fnkcom := byte('C');
  377.       fnkcomv := modcomv;
  378.     end;
  379.     4: {vibrato}
  380.     begin
  381.       fnkcom := byte('D');
  382.       fnkcomv := modcomv;
  383.     end;
  384.     5: {porta note + volslide}
  385.     begin
  386.       convert_slide;
  387.     end;
  388.     6: {vibrato + volslide}
  389.     begin
  390.       convert_slide;
  391.     end;
  392.     7: {tremolo}
  393.     begin
  394.       fnkcom := byte('K');
  395.       fnkcomv := modcomv;
  396.     end;
  397.     9: {sample offset}
  398.     begin
  399.       fnkcom := byte('M');
  400.       fnkcomv := modcomv;
  401.     end;
  402.     $a: {Volume Slide}
  403.     begin
  404.       convert_slide;
  405.     end;
  406.     $c: {set volume}
  407.     begin
  408.       fnkcom := byte('N');
  409.       {$r-}
  410.       xxx := trunc((modcomv * 256) / 64);
  411.       if xxx = 256 then
  412.       begin
  413.         xxx := 255;
  414.       end;
  415.       fnkcomv := xxx;
  416.       {$r+}
  417.     end;
  418.     $d: {pattern break}
  419.     begin
  420.       fnkheader.break_list[pattern] := treks;
  421.     end;
  422.     $e: {command e}
  423.     begin
  424.       case (modcomv shr 4) of
  425.         1: {fine slideup}
  426.         begin
  427.           fnkcom := byte('O');
  428.           fnkcomv := $40 or (modcomv and $f);
  429.         end;
  430.         2: {fine slidedn}
  431.         begin
  432.           fnkcom := byte('O');
  433.           fnkcomv := $50 or (modcomv and $f);
  434.         end;
  435.         4: {Vibrato command}
  436.         begin
  437.         end;
  438.         7: {tremolo command}
  439.         begin
  440.         end;
  441.         9: {retrig note}
  442.         begin
  443.           fnkcom := byte('O');
  444.           fnkcomv := $D0 or (modcomv and $f);
  445.         end;
  446.         $a: {fine volume up}
  447.         begin
  448.           fnkcom := byte('O');
  449.           fnkcomv := $60 or (modcomv and $f);
  450.         end;
  451.         $b: {fine volume dn}
  452.         begin
  453.           fnkcom := byte('O');
  454.           fnkcomv := $70 or (modcomv and $f);
  455.         end;
  456.         $c: {note cut}
  457.         begin
  458.           fnkcom := byte('O');
  459.           fnkcomv := $01 or (modcomv and $f);
  460.         end;
  461.       end;
  462.     end;
  463.     $f: {set tempo}
  464.     begin
  465.       fnkcom := byte('O');
  466.       if modcomv > 0 then
  467.       begin
  468.         dec(modcomv);
  469.       end;
  470.       fnkcomv := $f0 or (modcomv and $f);
  471.     end;
  472.   end;
  473.   fnkcom := fnkcom - byte('A');
  474. end;
  475.  
  476. procedure convert_slot(mod_slot : tmodslot; var fnk_slot : tfnkslot);
  477. var
  478.   note     : word;
  479.   note2    : byte;
  480.   sample   : byte;
  481.   command  : byte;
  482.   commval  : byte;
  483.   fnkcom   : byte;
  484.   fnkcomv  : byte;
  485. begin
  486.   asm
  487.     mov    ax,word[mod_slot.byte1]
  488.     xchg   al,ah
  489.     and    ax,0fffh
  490.     mov    note,ax
  491.   end;
  492.   note2 := mod_notematcher(note);
  493.   sample := (mod_slot.byte3 shr 4) or (mod_slot.byte1 and $f0);
  494.   command := mod_slot.byte3 and $f;
  495.   commval := mod_slot.byte4;
  496.  
  497.   if note <> 0 then
  498.   begin
  499.     if sample = 0 then
  500.     begin
  501.       sample := oldsample[channels];
  502.     end
  503.     else
  504.     begin
  505.       oldsample[channels] := sample;
  506.     end;
  507.  
  508.     if sample > 0 then
  509.     begin
  510.       dec(sample);
  511.       fnk_slot.byte1 := note2 shl 2;
  512.       fnk_slot.byte2 := $f;
  513.       fnk_slot.byte1 := fnk_slot.byte1 or ((sample shr 4) and 3);
  514.       fnk_slot.byte2 := fnk_slot.byte2 or ((sample and 15) shl 4);
  515.     end;
  516.   end;
  517.  
  518.   if (command > 0) and (commval > 0) then
  519.   begin
  520.     convert_command(command, commval, fnkcom, fnkcomv);
  521.     fnk_slot.byte2 := fnk_slot.byte2 and $f0;
  522.     fnk_slot.byte2 := fnk_slot.byte2 or (fnkcom and $f);
  523.     fnk_slot.byte3 := fnkcomv;
  524.   end;
  525. end;
  526.  
  527. {
  528. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  529. ;                                                                          ;
  530. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  531. }
  532. procedure convert_patterns;
  533. var
  534.   numpatterns   : byte;
  535.   x             : byte;
  536.   no_channels   : byte;
  537.   pattern_total : longint;
  538. begin
  539.   pattern_total := 0;
  540.   write(#10);
  541.   case mod_type of
  542.     FOURCHAN_MOD:  no_channels := 4;
  543.     EIGHTCHAN_MOD: no_channels := 8;
  544.   end;
  545.  
  546.   numpatterns := 0;
  547.   for x := 1 to 128 do
  548.   begin
  549.     if modheader.sequences[x] > numpatterns then
  550.     begin
  551.       numpatterns := modheader.sequences[x];
  552.     end;
  553.   end;
  554.   inc(numpatterns);
  555.  
  556.   oldsample[0] := 0;
  557.   oldsample[1] := 0;
  558.   oldsample[2] := 0;
  559.   oldsample[3] := 0;
  560. {convert mod patterns}
  561.   for pattern := 1 to numpatterns do
  562.   begin
  563.     blockread(modfile, modpattern, sizeof(tmodslot)*(64*no_channels), rws);
  564.  
  565.     for treks := 0 to 63 do
  566.     begin
  567.       for channels := 0 to 7 do
  568.       begin
  569.         fnkpattern[channels+(treks*8)].byte1 := $fc;
  570.         fnkpattern[channels+(treks*8)].byte2 := $f;
  571.         fnkpattern[channels+(treks*8)].byte3 := 0;
  572.       end;
  573.     end;
  574.     for treks := 0 to 63 do
  575.     begin
  576.       for channels := 0 to (no_channels-1) do
  577.       begin
  578.         convert_slot(modpattern[channels+(treks*no_channels)], fnkpattern[channels+(treks*8)])
  579.       end;
  580.     end;
  581.     blockwrite(funkfile, fnkpattern, sizeof(tfnkslot)*(64*8), rws);
  582.     pattern_total := pattern_total + rws;
  583.     write('patterns : ',pattern:8,', ',pattern_total:8,' bytes',#13);
  584.   end;
  585. end;
  586.  
  587. {
  588. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  589. ;                                                                          ;
  590. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  591. }
  592. const
  593.   MOD_tune_table      : array[0..15] of word = (
  594.   ($369e9a div 0428),
  595.   ($369e9a div 0425),
  596.   ($369e9a div 0422),
  597.   ($369e9a div 0419),
  598.   ($369e9a div 0416),
  599.   ($369e9a div 0413),
  600.   ($369e9a div 0410),
  601.   ($369e9a div 0407),
  602.   ($369e9a div 0453),
  603.   ($369e9a div 0450),
  604.   ($369e9a div 0447),
  605.   ($369e9a div 0444),
  606.   ($369e9a div 0441),
  607.   ($369e9a div 0437),
  608.   ($369e9a div 0434),
  609.   ($369e9a div 0431));
  610.  
  611. procedure convert_samples_etc;
  612. var
  613.   rws2              : word;
  614.   sample_block_size : longint;
  615.   x                 : word;
  616.   read_length       : word;
  617.   truct             : longint;
  618.   saminfreqinc      : real;
  619.   saminpos          : real;
  620.   samoutpos         : word;
  621.  
  622. procedure write_block;
  623. begin
  624.   if samoutpos > 0 then
  625.   begin
  626.     blockwrite(funkfile, trans_buffer2, samoutpos, rws2);
  627.     samoutpos := 0;
  628.     sample_block_size := sample_block_size + rws;
  629.     fnkheader.samples[x].length := fnkheader.samples[x].length + rws2;
  630.   end;
  631. end;
  632.  
  633. procedure trans_block;
  634. begin
  635.   fnkheader.samples[x].length := 0;
  636.   if read_length > 0 then
  637.   begin
  638.     repeat
  639.       if read_length > fnbuf_size then
  640.       begin
  641.         blockread(modfile, trans_buffer1, fnbuf_size, rws);
  642.       end
  643.       else
  644.       begin
  645.         blockread(modfile, trans_buffer1, read_length, rws);
  646.       end;
  647.       read_length := read_length - rws;
  648.  
  649.       if rws > 0 then
  650.       begin
  651.         saminpos := 0;
  652.         samoutpos := 0;
  653.         saminfreqinc := MOD_tune_table[modheader.samples[x].sfinetune] / MOD_tune_table[0];
  654.         repeat
  655.           if samoutpos = fnbuf_size then
  656.           begin
  657.             write_block;
  658.           end;
  659.           if trunc(saminpos) < rws then
  660.           begin
  661.             trans_buffer2[samoutpos] := trans_buffer1[trunc(saminpos)];
  662.             inc(samoutpos);
  663.             saminpos := saminpos + saminfreqinc;
  664.           end;
  665.         until trunc(saminpos) >= rws;
  666.         write_block;
  667.       end;
  668.     until rws = 0;
  669.   end;
  670. end;
  671.  
  672. procedure skip_block;
  673. begin
  674.   if read_length > 0 then
  675.   begin
  676.     repeat
  677.       if read_length > fnbuf_size then
  678.       begin
  679.         blockread(modfile, trans_buffer1, fnbuf_size, rws);
  680.       end
  681.       else
  682.       begin
  683.         blockread(modfile, trans_buffer1, read_length, rws);
  684.       end;
  685.       read_length := read_length - rws;
  686.     until rws = 0;
  687.   end;
  688. end;
  689.  
  690. begin
  691.   write(#10);
  692.   sample_block_size := 0;
  693.  
  694.   for x := 1 to 31 do
  695.   begin
  696.     truct := 0;
  697.     if modheader.samples[x].sreplen > 2 then
  698.     begin
  699.       read_length := (modheader.samples[x].srepeat + modheader.samples[x].sreplen);
  700.       if read_length > modheader.samples[x].slength then
  701.       begin
  702.         read_length := modheader.samples[x].slength;
  703.         trans_block;
  704.       end
  705.       else
  706.       begin
  707.         trans_block;
  708.         read_length := modheader.samples[x].slength  - (modheader.samples[x].srepeat + modheader.samples[x].sreplen);
  709.         truct := read_length;
  710.         skip_block;
  711.       end;
  712.     end
  713.     else
  714.     begin
  715.       read_length := modheader.samples[x].slength;
  716.       trans_block;
  717.     end;
  718.     write('sample ',x:2,': ',fnkheader.samples[x].length:8,',',
  719.           fnkheader.samples[x].start:8,',',sample_block_size:8,
  720.           ' bytes          ',#13);
  721.     if modheader.samples[x].sfinetune = 7 then
  722.     begin
  723.       writeln(#10'    WARNING: FUNKTRACKER DOESN`T HAVE FINETUNE. PLEASE RESAMPLE.');
  724.     end;
  725.     if truct > 0 then
  726.     begin
  727.       writeln(#10'    WARNING: UNUSED SAMPLE LOOP TRUCATED BY ',truct,' bytes.');
  728.     end;
  729.   end;
  730.  
  731.   fnkheader.info[4] := byte(sample_block_size shr 18);
  732.   fnkheader.LZH_check_size := filesize(funkfile);
  733.   seek(funkfile, sizeof(tfnkheader) - sizeof(tfnksamples));
  734.   fnkheader.LZH_check_sum := 0;
  735.   repeat
  736.     blockread(modfile, trans_buffer1, fnbuf_size, rws);
  737.     if rws <> 0 then
  738.     begin
  739.       for x := 0 to (rws-1) do
  740.       begin
  741.         fnkheader.LZH_check_sum := fnkheader.LZH_check_sum + trans_buffer1[x];
  742.       end;
  743.     end;
  744.   until rws = 0;
  745.   seek(funkfile, 0);
  746.   blockwrite(funkfile, fnkheader, sizeof(tfnkheader) - sizeof(tfnksamples), rws);
  747. end;
  748.  
  749. {
  750. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  751. ;                                                                          ;
  752. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  753. }
  754. var
  755. as : byte;
  756. begin
  757.   if ParamStr(1) = '' then
  758.   begin
  759.     writeln('MOD2FNK ',version, '-                 Converts ProTracker modules to FunkTracker format');
  760.     writeln('───────────────────────────────────────────────────────────────────────────────');
  761.     writeln('Command: MOD2FNK <modfile>');
  762.   end
  763.   else
  764.   begin
  765.     as := pos('.', ParamStr(1));
  766.     if as > 0 then
  767.     begin
  768.       newstr := copy(ParamStr(1),1, pos('.', ParamStr(1))-1);
  769.     end
  770.     else
  771.     begin
  772.       newstr := ParamStr(1);
  773.     end;
  774.     assign(modfile, newstr + '.MOD');
  775.     reset(modfile, 1);
  776.     if ioresult = 0 then
  777.     begin
  778.       assign(funkfile, newstr + '.FNK');
  779.       rewrite(funkfile,1);
  780.       if ioresult = 0 then
  781.       begin
  782.         if convert_header then
  783.         begin
  784.           convert_patterns;
  785.           convert_samples_etc;
  786.         end;
  787.         close(funkfile);
  788.       end;
  789.       close(modfile);
  790.       writeln(#10,'Successfully converted.');
  791.  
  792.     end
  793.     else
  794.     begin
  795.       writeln;
  796.       writeln('MOD file not found.');
  797.     end;
  798.   end;
  799. end.