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