Advertisement
Guest User

Untitled

a guest
Sep 29th, 2017
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
QBasic 17.44 KB | None | 0 0
  1. #COMPILE EXE
  2. #DIM NONE
  3.  
  4. FUNCTION PBMAIN () AS LONG
  5.  
  6.     '************************************
  7.     '* XM2ESF/oerg               v0.057 *
  8.     '************************************
  9.     '
  10.     ' Converts XM-format module music to
  11.     ' Echo Stream Format
  12.     '
  13.     '
  14.     ' (C) 2009, 2010, 2011 Oerg866
  15.     '
  16.     ' XM Splitter (C) 2007 Nineko
  17.     '
  18.  
  19.  
  20.     PRINT "XM2ESF - Convert XM to Echo Stream Format"
  21.     PRINT ""
  22.     PRINT "*** ALPHA VERSION 0.0.57a ***"
  23.     PRINT ""
  24.     PRINT "THIS PROGRAM IS FREEWARE!"
  25.     PRINT ""
  26.     PRINT "Copyright (C) 2011 Oerg866 Software, inc."
  27.     PRINT ""
  28.     IF COMMAND$ = "" THEN
  29.         PRINT "usage: xm2esf <infile> <outfile>"
  30.     END IF
  31.  
  32.     OPEN COMMAND$(1) FOR INPUT AS #1
  33.  
  34.     DIM xmfm&(1 TO 6)
  35.     DIM xmpsg&(1 TO 3)
  36.     DIM fm&
  37.     DIM psg&
  38.  
  39.     tempo& = 7      ' Default tempo :P
  40.  
  41.     WHILE setting$ <> "[Instruments]"
  42.         LINE INPUT #1, setting$
  43.         IF MID$(setting$, 1, 1) <> "#" THEN
  44.            SELECT CASE spleft(setting$)
  45.  
  46.               CASE "FILE"
  47.                 xm$ = param(setting$, 1)
  48.                 PRINT "XM File: " + xm$
  49.               CASE "TYPE"
  50.                 SELECT CASE param(setting$, 1)
  51.                 CASE "BGM"
  52.                 filetype& = 1
  53.                 CASE "SFX"
  54.                 filetype& = 2
  55.                 END SELECT
  56.                 SELECT CASE param(setting$, 2)
  57.                 CASE "LOOP"
  58.  
  59.                 esfloop& = 1
  60.                 IF filetype& = 2 THEN
  61.                     PRINT "Input file errorneously declares loop while being a SFX. File rejected."
  62.                     PRINT "Press any key!"
  63.                     WAITKEY$
  64.                     CLOSE
  65.                     EXIT FUNCTION
  66.                 END IF
  67.                 CASE "NOLOOP"
  68.                 esfloop& = 0
  69.  
  70.  
  71.                 END SELECT
  72.  
  73.               CASE "TEMPO"
  74.                   tempo& = VAL(param(setting$, 1))
  75.               CASE "FM"
  76.                   fm& = VAL(param(setting$, 1))
  77.                   IF fm > 6 THEN
  78.                       PRINT "Declared more than 6 FM channels. Press any key!"
  79.  
  80.                   WAITKEY$:CLOSE:EXIT FUNCTION
  81.                   END IF
  82.               CASE "PSG"
  83.                   psg& = VAL(param(setting$, 1))
  84.                   IF psg& > 3 THEN
  85.                       PRINT "Declared more than 3 PSG channels. Press any key!"
  86.                       PRINT "Press any key!"
  87.                       WAITKEY$
  88.                       CLOSE
  89.                       EXIT FUNCTION
  90.                   END IF
  91.               CASE "PCM"
  92.                   pcm& = 1
  93.                   IF fm& = 6 THEN
  94.                       PRINT "Input file errorneously declares PCM even though 6 FM channels are used"
  95.                       PRINT "Press any key!"
  96.                       WAITKEY$
  97.                       CLOSE
  98.                       EXIT FUNCTION
  99.  
  100.                   END IF
  101.               CASE "NOISE"
  102.                   noise& = VAL(param(setting$, 1))
  103.               CASE "FM1"
  104.                   xmfm&(1) = VAL(param(setting$, 1))
  105.               CASE "FM2"
  106.                   xmfm&(2) = VAL(param(setting$, 1))
  107.               CASE "FM3"
  108.                   xmfm&(3) = VAL(param(setting$, 1))
  109.               CASE "FM4"
  110.                   xmfm&(4) = VAL(param(setting$, 1))
  111.               CASE "FM5"
  112.                   xmfm&(5) = VAL(param(setting$, 1))
  113.               CASE "FM6"
  114.                   xmfm&(6) = VAL(param(setting$, 1))
  115.               CASE "PCMC"
  116.                   xmpcm& = VAL(param(setting$,1))
  117.               CASE "PSG1"
  118.                   xmpsg&(1) = VAL(param(setting$, 1))
  119.               CASE "PSG2"
  120.                   xmpsg&(2) = VAL(param(setting$, 1))
  121.               CASE "PSG3"
  122.                   xmpsg&(3) = VAL(param(setting$, 1))
  123.               CASE "PSGN"
  124.                   xmnoise& = VAL(param(setting$, 1))
  125.               CASE "NOISETYPE"
  126.                   noisetype& = VAL(param(setting$, 1))
  127.  
  128.            END SELECT
  129.         END IF
  130.  
  131.     WEND
  132.  
  133.     s$ = "loadxm " + xm$
  134.     PRINT "Shell step: " + s$
  135.  
  136.     SHELL s$
  137.  
  138.     'INSTRUMENT ASSIGNMENTS
  139.     DIM esfins&(1 TO 256)
  140.  
  141.     WHILE setting$ <> "[Pitch]"
  142.  
  143.         IF MID$(setting$,1,1) <> "#" THEN
  144.  
  145.         LINE INPUT #1, setting$
  146.         esfins&(VAL(spleft(setting$))) = VAL("&H" + param(setting$,1))
  147.  
  148.         END IF
  149.  
  150.     WEND
  151.  
  152.     'PITCH
  153.  
  154.     ' 123456 = FM
  155.     ' 789    = PSG
  156.  
  157.     ' 11     = PCM
  158.     ' 10     = NSE
  159.  
  160.  
  161.  
  162.     DIM pitch&(1 TO 11)
  163.  
  164.     WHILE setting$ <> "[Volume]"
  165.         IF MID$(setting$,1,1) <> "#" THEN
  166.  
  167.             SELECT CASE spleft(setting$)
  168.                 CASE "FM1"
  169.                     pitch&(1) = VAL(param(setting$,1))
  170.                 CASE "FM2"
  171.                     pitch&(2) = VAL(param(setting$,1))
  172.                 CASE "FM3"
  173.                     pitch&(3) = VAL(param(setting$,1))
  174.                 CASE "FM4"
  175.                     pitch&(4) = VAL(param(setting$,1))
  176.                 CASE "FM5"
  177.                     pitch&(5) = VAL(param(setting$,1))
  178.                 CASE "FM6"
  179.                     pitch&(6) = VAL(param(setting$,1))
  180.  
  181.                 CASE "PSG1"
  182.                     pitch&(7) = VAL(param(setting$,1))
  183.                 CASE "PSG2"
  184.                     pitch&(8) = VAL(param(setting$,1))
  185.                 CASE "PSG3"
  186.                     pitch&(9) = VAL(param(setting$,1))
  187.                 END SELECT
  188.         END IF
  189.  
  190.  
  191.     WEND
  192.  
  193.     DIM pitch&(1 TO 11)
  194.  
  195.     WHILE setting$ <> "[END]"
  196.         IF MID$(setting$,1,1) <> "#" THEN
  197.  
  198.             SELECT CASE spleft(setting$)
  199.                 CASE "FM1"
  200.                     vol&(1) = VAL(param(setting$,1))
  201.                 CASE "FM2"
  202.                     vol&(2) = VAL(param(setting$,1))
  203.                 CASE "FM3"
  204.                     vol&(3) = VAL(param(setting$,1))
  205.                 CASE "FM4"
  206.                     vol&(4) = VAL(param(setting$,1))
  207.                 CASE "FM5"
  208.                     vol&(5) = VAL(param(setting$,1))
  209.                 CASE "FM6"
  210.                     vol&(6) = VAL(param(setting$,1))
  211.  
  212.                 CASE "PSG1"
  213.                     vol&(7) = VAL(param(setting$,1))
  214.                 CASE "PSG2"
  215.                     vol&(8) = VAL(param(setting$,1))
  216.                 CASE "PSG3"
  217.                     vol&(9) = VAL(param(setting$,1))
  218.                 CASE "PSG3"
  219.                     vol&(9) = VAL(param(setting$,1))
  220.                 CASE "PSGN"
  221.                     vol&(10) = VAL(param(setting$,1))
  222.                 END SELECT
  223.         END IF
  224.  
  225.  
  226.     WEND
  227.     '
  228.     CLOSE
  229.  
  230.     OPEN COMMAND$(2) FOR BINARY AS #20
  231.  
  232.  
  233.     DIM i AS INTEGER
  234.     DIM present&(1 TO 11)
  235.     FOR i = 1 TO fm&
  236.  
  237.     present&(i) = 1
  238.     OPEN "temp\C" + TRIM$(STR$(xmfm&(i))) + ".tmp" FOR BINARY AS #i
  239.  
  240.     NEXT i
  241.  
  242.     FOR i = 7 TO psg& + 6
  243.     present&(i) = 1
  244.  
  245.     OPEN "temp\C" + TRIM$(STR$(xmpsg&(i-6))) + ".tmp" FOR BINARY AS #i
  246.  
  247.     NEXT i
  248.  
  249.     IF pcm& = 1 THEN
  250.  
  251.     present&(11) = 1
  252.     OPEN "temp\C" + TRIM$(STR$(xmpcm&)) + ".tmp" FOR BINARY AS #11
  253.  
  254.     END IF
  255.  
  256.     IF noise& = 1 THEN
  257.  
  258.     present&(10) = 1
  259.     OPEN "temp\C" + TRIM$(STR$(xmnoise&)) + ".tmp" FOR BINARY AS #10
  260.  
  261.     END IF
  262.     '       $00nn ..... Note on FM channel #1
  263.     '       $01nn ..... Note on FM channel #2
  264.     '       $02nn ..... Note on FM channel #3
  265.     '       $04nn ..... Note on FM channel #4
  266.     '       $05nn ..... Note on FM channel #5
  267.     '       $06nn ..... Note on FM channel #6
  268.     '       $08nn ..... Note on PSG channel #1
  269.     '       $09nn ..... Note on PSG channel #2
  270.     '       $0Ann ..... Note on PSG channel #3
  271.     '       $0Bnn ..... Note on PSG channel #4
  272.     '       $0Cnn ..... Note on PCM channel
  273.     '
  274.     '
  275.  
  276.     DIM esfchan&(1 TO 11)
  277.  
  278.     esfchan&(1)  = 0
  279.     esfchan&(2)  = 1
  280.     esfchan&(3)  = 2
  281.     esfchan&(4)  = 4
  282.     esfchan&(5)  = 5
  283.     esfchan&(6)  = 6
  284.     esfchan&(7)  = 8
  285.     esfchan&(8)  = 9
  286.     esfchan&(9)  = 10
  287.     esfchan&(10) = 11
  288.     esfchan&(11) = 12
  289.  
  290.     DIM fmnote&(1 TO 11)
  291.  
  292.     fmnote&(0) = 644
  293.     fmnote&(1) = 681
  294.     fmnote&(2) = 722
  295.     fmnote&(3) = 765
  296.     fmnote&(4) = 810
  297.     fmnote&(5) = 858
  298.     fmnote&(6) = 910
  299.     fmnote&(7) = 964
  300.     fmnote&(8) = 1024
  301.     fmnote&(9) = 1081
  302.     fmnote&(10) = 1146
  303.     fmnote&(11) = 1214
  304.  
  305.     DIM psgnote&(0 TO 96)
  306.     OPEN "psg.txt" FOR INPUT AS #1
  307.  
  308.     t&=0
  309.     WHILE NOT EOF(1)
  310.  
  311.     LINE INPUT #1, c$
  312.     psgnote&(t&) = VAL(c$)
  313.  
  314.     t&=t&+1
  315.     WEND
  316.     CLOSE #1
  317.  
  318.     '            freq& = INT(fmnote&(subtone&) * (2^octave&))
  319.  
  320.     DIM ctype(1 TO 11)  AS INTEGER
  321.     ctype(7) = 1
  322.     ctype(8) = 1
  323.     ctype(9) = 1
  324.     ctype(10) = 2 'pcm
  325.     ctype(11) = 3 'noise
  326.  
  327.     OPEN "temp\file.inf" FOR INPUT AS #1234
  328.     LINE INPUT #1234, a$
  329.     LINE INPUT #1234, a$: restart& = VAL(a$)
  330.     LINE INPUT #1234, a$: total& = VAL(a$)
  331.     CLOSE #1234
  332.  
  333.  
  334.     DIM effectdat&(1 TO 11)
  335.     DIM effectval&(1 TO 11)
  336.  
  337.     DIM row$(1 TO 11)
  338.     FOR i = 1 TO 11
  339.         row$(i) = "     "
  340.         effectdat&(i) = 255
  341.         effectval&(i) = 255
  342.     NEXT i
  343.  
  344.     DIM slidestep(1 TO 11) AS DOUBLE
  345.  
  346.     DIM slidetarget&(1 TO 11)
  347.  
  348.     DIM slidespeed&(1 TO 11)
  349.    
  350.     DIM volslidepos(1 TO 11) AS DOUBLE
  351.     DIM slidespeed&(1 TO 11) AS DOUBLE
  352.  
  353.     DIM curins&(1 TO 11)
  354.     DIM curnote&(1 TO 11)
  355.     DIM curvol&(1 TO 11)
  356.     DIM curfreq&(1 TO 9)
  357.     DIM xmins&
  358.  
  359.     DIM currow AS LONG
  360.  
  361.     FOR currow = 1 TO total&
  362.         IF currow = restart& THEN
  363.             IF esfloop& = 1 THEN PUT$ #20, CHR$(&hFD)
  364.         END IF
  365.  
  366.         FOR i = 1 TO 11
  367.             IF present&(i) = 1 THEN
  368.  
  369.                 GET #i, , row$(i)
  370.                 xmnote&=      ASC(MID$(row$(i), 1, 1))
  371.                 xmins& =      ASC(MID$(row$(i), 2, 1))
  372.                 xmvol& =      ASC(MID$(row$(i), 3, 1))
  373.                 xmeff& =      ASC(MID$(row$(i), 4, 1))
  374.                 xmeffdat& =   ASC(MID$(row$(i), 5, 1))
  375.  
  376. ' TEMP: Converting XM volume to FM volume (formula supplied by sik)
  377.  
  378. '-(int(log10(x / 63.0) * 63))
  379.  
  380.                
  381.                 IF xmeff& = 3 THEN
  382.  
  383.                     IF ctype(i) = 1 AND xmnote& <> 97 THEN
  384.                        slidetarget&(i) = xmnote& + pitch&(i)
  385.                        slidestep(i) = curnote&(i)
  386.                        slidespeed&(i) = xmeffdat&
  387.                     END IF
  388.                 END IF
  389.                
  390.                 IF xmnote& < 97 AND xmnote& > 0 THEN IF xmeff& < 1 OR xmeff& > 3 THEN curnote&(i) = xmnote&
  391.                  
  392.                 IF xmeff& = 2 THEN
  393.                        slidestep(i) = curnote&(i)
  394.                        slidespeed&(i) = xmeffdat&
  395.                        sliDetarget&(i) = 0
  396.                 END IF
  397.                
  398.                 IF xmnote& = 97 THEN
  399.  
  400.                     PUT$ #20, CHR$(esfchan&(i))
  401.  
  402.                 END IF
  403.  
  404.  
  405.                 IF xmnote& > 0 AND xmnote& < 97 THEN
  406.  
  407.                    IF ctype(i) = 0 OR ctype(i) = 1 THEN
  408.                             SELECT CASE effEctdat&(i)
  409.                                 CASE 1 TO 3
  410.                                     EXIT IF
  411.                             END SELECT
  412.  
  413.                             curnote&(i) = xmnote& + pitch&(i)
  414.  
  415.                             'instrument being 0 means that we play the note as if the instrument is the same
  416.                             IF curins&(i) <> xmins& THEN
  417.                               Curins&(i) = xmins&
  418.                               IF ctype(i) = 0 OR Ctype(i) = 1 THEN
  419.  
  420.                                 PUT$ #20, CHR$(&H40 + esfchan&(i))
  421.                                 PUT$ #20, CHR$(esfins&(curins&(i)))
  422.  
  423.                               END IF
  424.                             END IF
  425.  
  426.                             IF ctype(i) = 0 THEN
  427.  
  428.                                 PUT$ #20, CHR$(esfchan&(i))
  429.                                 PUT$ #20, CHR$(32 * INT(curnote&(i) / 12) + (2 * (curnote&(i) MOD 12)) + 1)
  430.  
  431.                             ELSEIF ctype(i) = 1 THEN
  432.  
  433.                                 PUT$ #20, CHR$(esfchan&(i))
  434.                                 PUT$ #20, CHR$(24 * INT(curnote&(i) / 12) + (2 * (curnote&(i) MOD 12)))
  435.  
  436.                             END IF
  437.  
  438.  
  439.                     ELSEIF ctype(i) = 2
  440.  
  441.                             curins&(i) = xmins&
  442.                             PUT$ #20, CHR$(esfchan&(i))
  443.                             PUT$ #20, CHR$(esfins&(curins&(i)))
  444.  
  445.                     ELSEIF ctype(i) = 3
  446.  
  447.                             IF curins&(i) <> xmins& THEN
  448.                               Curins&(i) = xmins&
  449.  
  450.                                 PUT$ #20, CHR$(&H40 + esfchan&(i))
  451.                                 PUT$ #20, CHR$(esfins&(curins&(i)))
  452.  
  453.                               END IF
  454.                             END IF
  455.  
  456.  
  457.  
  458.                     END IF
  459.  
  460.                 END IF
  461.  
  462.  
  463.  
  464.                 IF xmeff& = &HC THEN
  465.                  IF ctype(i) = 0 THEN
  466.                     effectdat&(i) = &HC
  467.                     effectval&(i) = xmeffdat&
  468.                     PUT$ #20, CHR$(esfchan&(i) + &H20)
  469.                     PUT$ #20, CHR$(&h7f-(INT(LOG10(xmeffdat& / 63.0) * 63)))
  470.  
  471.                   ELSEIF ctype(i)=1 THEN
  472.  
  473.                     effectdat&(i)= &HC
  474.                     effectval&(i) = xmeffdat&
  475.                     PUT$ #20, CHR$(esfchan&(i) + &H20)
  476.                     PUT$ #20, CHR$(&h0f-(INT(LOG10(xmeffdat& / 15.0) * 15)))
  477.  
  478.                   ELSE
  479.                       'ignore for pcm +noise
  480.                       effectdat&(i) = 255
  481.                       effectval&(i) = 255
  482.                   END IF
  483.                  END IF
  484.  
  485.  
  486.  
  487.  
  488.  
  489.             END IF
  490.         NEXT i
  491.  
  492.         FOR pf& = 1 TO tempo&
  493.         ' PROCESS EFFECTS
  494.  
  495.             FOR i = 1 TO 11
  496.  
  497.                 SELECT CASE effectdate&(cprocess&)
  498.  
  499.                 CASE 1 TO 2
  500.                    
  501.                     IF ctype(i) <> 2 THEN
  502.                         IF effectdat&(cprocess&) slidestep(i) = slidestep(i) + slidespeed&(i) / 10
  503.                         IF slidetarget&(i) < slidestep(i) THEN slidestep(i) = slidetarget&(i)
  504.                         IF ctype(i)= 3 THEN
  505.                             PUT$ #20, CHR$(&h3A)
  506.                         ELSE
  507.                             PUT$ #20, CHR$(esfchan&(i) + &H30)
  508.                         END IF
  509.                        
  510.                         SELECT CASE ctype(i)
  511.                             CASE 0
  512.                                 curfreq&(i) = INT(644*(2^(slidestep(i)/12)))
  513.                                 PUT$ #20, CHR$(INT(curfreq&(i) / 256)) + CHR$(curfreq&(i) MOD 256)
  514.                             CASE 1 OR 2
  515.                                 curfreq&(i) = INT((0.5^(slidestep(i)/12))/2*851)
  516.                                 PUT$ #20, = CHR$(INT(curfreq&(i) MOD 16)) + CHR$(curfreq&(i) / 16)
  517.                         END SELECT
  518.                     END IF
  519.                    
  520.                 CASE 3
  521.  
  522.                     slidestep(i) = slidestep(i) + slidespeed&(i) / 10
  523.                     IF slidetarget&(i) < slidestep(i) THEN slidestep(i) = slidetarget&(i)
  524.                      
  525.                     ' Note slide :D!
  526.  
  527.                     IF ctype(i) = 0 THEN
  528.                        
  529.                      curfreq&(i) = INT(644*(2^(slidestep(i)/12)))
  530.                      PUT$ #20, CHR$(esfchan&(i) + &H30)
  531.                      PUT$ #20, CHR$(INT(curfreq&(i) / 256)) + CHR$(curfreq&(i) MOD 256)
  532.                      
  533.                        
  534.                     ELSEIF ctype(i) = 1 THEN
  535.  
  536.                      curfreq&(i) = INT((0.5^(slidestep(i)/12))/2*851)
  537.                      PUT$ #20, CHR$(esfchan&(i) + &H30)
  538.                      PUT$ #20, CHR$(INT(curfreq&(i) MOD 16)) + CHR$(curfreq&(i) / 16)
  539.  
  540.                     ELSEIF ctype(i) = 3 THEN
  541.  
  542.                     IF noisetype& = 1
  543.                      curfreq&(i) = INT((0.5^(slidestep(i)/12))/2*851)
  544.                      PUT$ #20, = CHR$(&h3A)    'PSG Channel 3
  545.                      PUT$ #20, = CHR$(INT(curfreq&(i) MOD 16)) + CHR$(curfreq&(i) / 16)
  546.                     END IF
  547.  
  548.  
  549.                         ' Ignore this effect for anything else
  550.  
  551.                     END IF
  552.  
  553.                 END SELECT
  554.             NEXT i
  555.  
  556.             PUT$ #20, CHR$(&HFE)
  557.             PUT$ #20, CHR$(&H1)
  558.         NEXT pf&
  559.     NEXT currow
  560.  
  561.     IF esfloop& = 0 THEN PUT$ #20, CHR$(&hFF)
  562.    
  563.     PRINT "Conversion done!"
  564.  
  565.     CLOSE
  566.  
  567. END FUNCTION
  568.  
  569. '                freq& = INT(fmnote&(subtone&) * (2^octave&))
  570. '                b$ = CHR$(INT(freq& / 256)) + CHR$(freq& MOD 256)
  571.  
  572. FUNCTION param(strn$, b&) AS STRING
  573.     c& = 0
  574.     i& = 1
  575.     car$ = MID$(strn$, 1, 1)
  576.     IF car$ = CHR$(34) THEN
  577.         comp$ = CHR$(34)
  578.         i& = 2
  579.         car$ = MID$(strn$, 2, 1)
  580.     ELSE
  581.         comp$ = " "
  582.     END IF
  583.     WHILE c& <> b&
  584.     WHILE car$ <> comp$
  585.           SPEFT$ = SPEFT$ + car$
  586.           i& = i& + 1
  587.           car$ = MID$(strn$, i&, 1)
  588.           IF i& > LEN(strn$) THEN
  589.               SPEFT$ = ""
  590.               param = SPEFT$
  591.               EXIT FUNCTION
  592.           END IF
  593.     WEND
  594.  
  595.    i& = i& + 1
  596.    c& = c& + 1
  597.    ' SPEFT$ = MID$(strn$, i&, 1)
  598.     car$ = SPEFT$
  599.     WEND
  600.  
  601.  
  602.     param = RTRIM$(spleft(MID$(strn$,i&)))
  603.  
  604. END FUNCTION
  605.  
  606. FUNCTION SPLEFT(strn$) AS STRING
  607.  
  608.     i& = 1
  609.     car$ = MID$(strn$, 1, 1)
  610.     IF car$ = CHR$(34) THEN
  611.         comp$ = CHR$(34)
  612.         i& = 2
  613.         car$ = MID$(strn$, 2, 1)
  614.     ELSE
  615.         comp$ = " "
  616.     END IF
  617.     WHILE car$ <> comp$
  618.           SPEFT$ = SPEFT$ + car$
  619.           i& = i& + 1
  620.           car$ = MID$(strn$, i&, 1)
  621.           IF i& > LEN(strn$) THEN
  622.               SPLEFT = SPEFT$ + cars$
  623.               EXIT FUNCTION
  624.           END IF
  625.     WEND
  626.               SPLEFT = SPEFT$
  627. END FUNCTION
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement