REM >!RunImage REM Copyright (c) 1994, Expressive Software Projects REM All rights reserved. REM REM Redistribution and use in source and binary forms, with or without REM modification, are permitted provided that the following conditions are met: REM * Redistributions of source code must retain the above copyright REM notice, this list of conditions and the following disclaimer. REM * Redistributions in binary form must reproduce the above copyright REM notice, this list of conditions and the following disclaimer in the REM documentation and/or other materials provided with the distribution. REM * Neither the name of Expressive Software Projects nor the names of its REM contributors may be used to endorse or promote products derived from REM this software without specific prior written permission. REM REM THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND REM ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED REM WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE REM DISCLAIMED. IN NO EVENT SHALL EXPRESSIVE SOFTWARE PROJECTS BE LIABLE FOR ANY REM DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES REM (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; REM LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND REM ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT REM (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS REM SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. REM d$=" (18 Apr 2007)" v$="1.37a" REM Sample Player - Using ESP Module REM MIDI Player - Using ESP MIDIPlay REM Version including WIMP File Message handling REM 1.35x Is first attempt at RealTime Synch REM 1.37 (26/32-bit neutral) on maintained by Liquid Silicon ON ERROR PROCErr PROCMakeDims PROCSet PROCStartWimp rcode%=FNCheckRealTime PROCLoadWimpSprites PROCLoadWindows PROCLoadMenus PROCGetType(TRUE,TRUE) REMPROCshadeIcon(playerWin%,playerMenuIcon%,TRUE):REM 1.37 - Didn't allow access to Control window when loading a sample before a MIDI file. PROCSetVolume(currentVolume%) ON ERROR PROCError PROCGo END REM --------------------------------------- DEFPROCGo quit%=FALSE Control%=0 oldmtime%=0 REPEAT PROCpoll IF playOn%=TRUE THEN CASE playType% OF WHEN playWAVE% SYS"Audio_Poll" TO posn%,stop%:REM ,R2%,R3%,R4%,R5% REM PROCe("R2="+STR$(R2%)+" R3="+STR$(R3%)+" R4="+STR$(R4%)+" R5="+STR$(R5%)) PROCSetTime(posn%) REM *********SYS "SharedSound_CheckDriver" REM SYS "SharedSound_CheckDriver" :REM 1.37 It needs this :REM for some reason to :REM fix sample rate REM SYS"Sound_LinearHandler",0 TO ,newHand% REM IF newHand%=0 THEN stop%=TRUE WHEN playMIDI% SYS"XMIDIPlay_Info" TO L%,posn%,stop%,mtext%:stop%=stop% EOR 1 IF ?mtext%<>mtx% THEN mtx%=?mtext% IF mtx%=1 THEN mtext$=FNstring(mtext%+1) ELSE mtext$=mtext$+FNstring(mtext%+1) ENDIF $MControlTextPtr%=mtext$ PROCSetIcon(MControlWin%,MControlText%,FALSE) ENDIF IF L%>midiLen% THEN midiLen%=L% REM PROCe("Len: "+STR$(midiLen%)+" posn:"+STR$(posn%)+" stop:"+STR$(stop%)) IF (stop%AND1) AND (NOT pause%) THEN IF loop% THEN stop%=FALSE posn%=0 SYS"XMIDIPlay_Start",0,posn% ELSE stop%=TRUE ENDIF ELSE stop%=FALSE PROCSetTime(posn%) ENDIF ENDCASE IF stop% THEN PROCStop(FALSE) PROCSetIcon(playerWin%,playerStop%,FALSE) posn%=0 ENDIF ENDIF IF dragOn% THEN MOUSE X%,Y%,B% CASE whichDrag% OF WHEN dragTime% PROCChangeTime(X%) WHEN dragVolume% PROCChangeVol(X%) WHEN dragTempo% PROCChangeTempo(X%) ENDCASE ENDIF UNTIL quit% PROCShutDown ENDPROC DEFPROCShutDown PROCStop(FALSE) IF playType%=playWAVE% THEN *RMREINIT SamplePlayer ENDIF SYS"Wimp_CloseDown",taskHandle%,Z% ENDPROC DEFPROCpoll SYS"Wimp_Poll",,pollSpace% TO reason% REM PROCe("Memory:"+STR$(HIMEM-END)) CASE reason% OF WHEN 1:REM PROCRedrawWindow WHEN 2:PROCOpenWindow(0,pollSpace%) WHEN 3:PROCCloseWindow(pollSpace%) WHEN 4:REM WHEN 5:REM WHEN 6:PROCMouse(!pollSpace%,pollSpace%!4,pollSpace%!8,pollSpace%!12,pollSpace%!16) WHEN 7:dragOn%=FALSE WHEN 8:REM Key WHEN 9:PROCDecodeMenu(pollSpace%) WHEN 17,18:REM Message CASE pollSpace%!16 OF WHEN 0:quit%=TRUE WHEN &400C1:REM Read mode OTHERWISE: PROCmessage ENDCASE ENDCASE ENDPROC REM ------------------- Mouse handling DEFPROCMouse(X%,Y%,button%,handle%,icon%) shift%=INKEY(-1) CASE handle% OF WHEN -2 CASE button% OF WHEN 4:PROCOpenWindow(playerWin%,-1) WHEN 2:PROCOpenMenu(iconMenuPtr%,iconMenuNum%,iconM%,X%,180) ENDCASE WHEN playerWin% AND button%<>2 :REM 1.37 Disable menu button CASE icon% OF WHEN playerMenuIcon%: CASE playType% OF WHEN playWAVE% PROCGetType(FALSE,FALSE) SYS"Wimp_CreateMenu",,optionWin%,X%,Y% WHEN playMIDI% SYS"Wimp_CreateMenu",,MControlWin%,X%,Y% ENDCASE WHEN playerPlay% : IF NOT playOn% THEN PROCPlay WHEN playerStop% : PROCStop(playOn%=FALSE) WHEN playerLoop% : loop%=NOT loop%:loopCount%=0:PROCLoop WHEN playerPause% : pause%=NOT pause%:PROCPause WHEN playerVolBar% : CASE button% OF WHEN 4 :PROCChangeVol(X%) WHEN 4*16:PROCstartDrag(handle%,icon%,X%,Y%,dragVolume%) ENDCASE WHEN playerTimeBar% : IF dataLoad% THEN CASE button% OF WHEN 4 :PROCChangeTime(X%) WHEN 4*16:PROCstartDrag(handle%,icon%,X%,Y%,dragTime%) ENDCASE ENDIF WHEN playerVolLeft% : PROCSetVolume((button%=4)+256*(button%=1)) WHEN playerVolRight%: PROCSetVolume((button%=1)+256*(button%=4)) WHEN playerMute% : mute%=NOT mute%:PROCMute WHEN playerRewind% : PROCMovePlay(-1+shift%*9) WHEN playerForward% : PROCMovePlay(1-shift%*9) ENDCASE WHEN optionWin% CASE icon% OF WHEN optionsSRateUp% :PROCRateChange(button%,4,1) WHEN optionsSRateDown%:PROCRateChange(button%,1,4) WHEN optionsRateMenu% :PROCOpenMenu(rateMenuPtr%,rateMenuNum%,rateM%,X%,Y%) WHEN optionsOK%: PROCStop(TRUE) IF button%=1 OR button%=4 THEN PROCGetType(TRUE,TRUE) IF button%=4 THEN SYS"Wimp_CreateMenu",,-1 WHEN optionsCancel% IF button%=4 THEN SYS"Wimp_CreateMenu",,-1 ENDCASE PROCGetType(TRUE,FALSE) WHEN MControlWin% CASE icon% OF WHEN MControlTempoLeft% : PROCSetTempo((button%=4)*(1-shift%*8)+(button%=1)*(shift%*8-1)) WHEN MControlTempoRight%: PROCSetTempo((button%=4)*(shift%*8-1)+(button%=1)*(1-shift%*8)) WHEN MControlTempoBar% : CASE button% OF WHEN 4 :PROCChangeTempo(X%) WHEN 4*16:PROCstartDrag(handle%,icon%,X%,Y%,dragTempo%) ENDCASE ENDCASE ENDCASE ENDPROC DEFPROCRateChange(button%,b1%,b2%) A%=VAL($optionsSRatePtr%) IF button%>-1 THEN IF button%=b1% THEN B%=A%+1-shift%*9 IF button%=b2% THEN B%=A%-1+shift%*9 IF B%>99999 THEN B%=99999 IF B%<1000 THEN B%=1000 ELSE B%=b1% ENDIF IF B%<>A% THEN SYS"Wimp_SetCaretPosition",-1 $optionsSRatePtr%=STR$(B%) !T%=optionWin%:T%!4=optionsSampleRate%:T%!8=0:T%!12=0 SYS"Wimp_SetIconState",,T% ENDIF ENDPROC DEFPROCChangeVol(X%) !Z%=playerWin% SYS "Wimp_GetWindowState",,Z% D%=Z%+256 !D%=playerWin% D%!4=playerVolBar% SYS"Wimp_GetIconState",,D% V%=(X%-(Z%!4)-(D%!8))/4 IF V%<0 THEN V%=0 IF V%>128 THEN V%=128 PROCSetVolume(V%) ENDPROC DEFPROCChangeTime(X%) LOCAL t%,p% !Z%=playerWin% SYS "Wimp_GetWindowState",,Z% D%=Z%+256 !D%=playerWin% D%!4=playerTimeBar% SYS"Wimp_GetIconState",,D% t%=(X%-(Z%!4)-(D%!8))/2 CASE playType% OF WHEN playWAVE% t%=(armLen%*t%)/barWidth% IF t%<0 THEN t%=0 IF t%>armLen% THEN t%=armLen% t%=((t%*8)/sampleBits%)/channels% WHEN playMIDI% t%=(midiLen%*t%)/barWidth% IF t%<0 THEN t%=0 IF t%>midiLen% THEN t%=midiLen% ENDCASE IF playOn% THEN p%=playOn% PROCStop(FALSE) posn%=t% IF p%=TRUE THEN PROCPlay ELSE PROCSetTime(posn%) ELSE posn%=t% PROCSetTime(posn%) ENDIF REM PROCe("Position = "+STR$(posn%)) ENDPROC DEFPROCChangeTempo(X%) LOCAL t%,p% !Z%=MControlWin% SYS "Wimp_GetWindowState",,Z% D%=Z%+256 !D%=MControlWin% D%!4=MControlTempoBar% SYS"Wimp_GetIconState",,D% t%=(X%-(Z%!4)-(D%!8))/2 t%=(tempoMax%*t%)/tempoWidth% IF t%<0 THEN t%=0 IF t%>tempoMax% THEN t%=tempoMax% PROCSetTempo(t%-tempo%) ENDPROC REM ---------------- Window handling DEFPROCOpenWindow(handle%,blk%) IF blk%<=0 THEN !Z%=handle% SYS "Wimp_GetWindowState",,Z% IF blk%<0 THEN Z%!28=-1 blk%=Z% ENDIF SYS "Wimp_OpenWindow",,blk% ENDPROC DEFPROCCloseWindow(blk%) SYS "Wimp_CloseWindow",,blk% ENDPROC DEFFNwindowOpen(H%):!Z%=H%:SYS"Wimp_GetWindowState",,Z%:=(((Z%!32) AND (1<<16))<>0) DEFFNwx(X%,R%)=X%-(R%!20)+(R%!4) DEFFNwy(Y%,R%)=Y%-(R%!24)+(R%!16) DEFPROCstartDrag(handle%,icon%,X%,Y%,which%) !Z%=handle% SYS"Wimp_GetWindowState",,Z% D%=Z%+256 !D%=handle% D%!4=icon% SYS"Wimp_GetIconState",,D% !T%=handle% T%!4=7 T%!8=X% T%!12=Y% T%!16=X% T%!20=Y% IF which%=dragTime% THEN O%=barWidth% ELSE O%=volWidth% O%=(((D%!16)-(D%!8))/2)-O% T%!24=FNwx(D%!8,Z%)+O% T%!28=FNwy(D%!12,Z%) T%!32=FNwx(D%!16,Z%)-O% T%!36=FNwy(D%!20,Z%) SYS"Wimp_DragBox",,T% whichDrag%=which% dragOn%=TRUE ENDPROC DEFPROCGetType(set%,player%) LOCAL V%,type%,bits,chans%,S%,rev%,inter% CASE playType% OF WHEN playMIDI%: $playerDescPtr%="MIDI" WHEN playWAVE%: IF player% THEN P%=playerDescPtr%:$P%="" IF set% THEN V%=FNwhichIcon(optionWin%,optionsTypeESG%) ELSE V%=-1 CASE V% OF WHEN optionsSignedLin% IF player% THEN $P%=$optionsSignedLinText% type%=signedLin% WHEN optionsUnsignedLin% IF player% THEN $P%=$optionsUnsignedLinText% type%=unsignedLin% WHEN optionsArcLog% IF player% THEN $P%=$optionsArcLogText% type%=arcLog% WHEN optionsADPCM% IF player% THEN $P%=$optionsADPCMText% type%=adpcm% OTHERWISE type%=sampleType% CASE sampleType% OF WHEN signedLin% A%=optionsSignedLinText% B%=optionsSignedLin% WHEN unsignedLin% A%=optionsUnsignedLinText% B%=optionsUnsignedLin% WHEN arcLog% A%=optionsArcLogText% B%=optionsArcLog% WHEN adpcm% A%=optionsADPCMText% B%=optionsADPCM% ENDCASE IF player% THEN $P%=$A% PROCSelectIcon(optionWin%,B%,optionsTypeESG%) ENDCASE CASE type% OF WHEN signedLin%,unsignedLin%: PROCshade(optionWin%,%0001,optionsBitsESG%) WHEN arcLog% PROCshade(optionWin%,%1101,optionsBitsESG%) PROCSelectIcon(optionWin%,optionsBits8%,optionsBitsESG%) WHEN adpcm% PROCshade(optionWin%,%1110,optionsBitsESG%) PROCSelectIcon(optionWin%,optionsBits4%,optionsBitsESG%) ENDCASE IF set% THEN V%=FNwhichIcon(optionWin%,optionsBitsESG%) ELSE V%=-1 IF V%=optionsBits4% AND (type%=signedLin% OR type%=unsignedLin%) THEN PROCSelectIcon(optionWin%,optionsBits8%,optionsBitsESG%) V%=optionsBits8% ENDIF CASE V% OF WHEN optionsBits4%: IF player% THEN $P%+=bit$(0) bits%=4 WHEN optionsBits8%: IF player% THEN $P%+=bit$(1) bits%=8 WHEN optionsBits12%: IF player% THEN $P%+=bit$(2) bits%=12 WHEN optionsBits16%: IF player% THEN $P%+=bit$(3) bits%=16 OTHERWISE: bits%=sampleBits% CASE sampleBits% OF WHEN 4 :B%=optionsBits4%:IF player% THEN $P%+=bit$(0) WHEN 8 :B%=optionsBits8%:IF player% THEN $P%+=bit$(1) WHEN 12:B%=optionsBits12%:IF player% THEN $P%+=bit$(2) WHEN 16:B%=optionsBits16%:IF player% THEN $P%+=bit$(3) ENDCASE PROCSelectIcon(optionWin%,B%,optionsBitsESG%) ENDCASE IF set% THEN V%=FNwhichIcon(optionWin%,optionsChannelsESG%) ELSE V%=-1 IF player% THEN $P%+=", " CASE V% OF WHEN optionsMono% IF player% THEN $P%+=$optionsMonoText% chans%=mono% WHEN optionsStereo% IF player% THEN $P%+=$optionsStereoText% chans%=stereo% OTHERWISE chans%=channels% CASE channels% OF WHEN mono%: A%=optionsMonoText%:B%=optionsMono% WHEN stereo%:A%=optionsStereoText%:B%=optionsStereo% ENDCASE IF player% THEN $P%+=$A% PROCSelectIcon(optionWin%,B%,optionsChannelsESG%) ENDCASE IF set% THEN rev%=FNiconSelected(optionWin%,optionsReversed%) ELSE rev%=reversed% PROCSetIcon(optionWin%,optionsReversed%,rev%) ENDIF IF player% THEN S%=VAL($optionsSRatePtr%) IF S%<1000 THEN PROCreport(sampleRateError%) PROCRateChange(-1,sampleRate%,0) ELSE IF type%=adpcm% THEN $optionsSRatePtr%=FNcheckRate(S%) ENDIF oldRate$=$optionsSRatePtr% sampleRate%=VAL(oldRate$) ENDIF $P%+=", "+$optionsSRatePtr%+" Hz" !T%=playerWin%:T%!4=playerDescription%:T%!8=0:T%!12=0 SYS"Wimp_SetIconState",,T% sampleType%=type% sampleBits%=bits% channels%=chans% reversed%=rev% PROCSetType PROCSetTimeDisplay ELSE IF NOT set% THEN $optionsSRatePtr%=STR$(sampleRate%) !T%=optionWin%:T%!4=optionsSampleRate%:T%!8=0:T%!12=0 SYS"Wimp_SetIconState",,T% ENDIF ENDIF OTHERWISE:$playerDescPtr%="" ENDCASE ENDPROC DEFFNcheckRate(S%) LOCAL bool%,N% I%=1:bool%=FALSE:N%=1 REPEAT IF STR$(S%)=menuList$(rateMenuPtr%+I%) THEN bool%=TRUE IF S%>VAL(menuList$(rateMenuPtr%+I%)) THEN N%=I% I%+=1 UNTIL bool% OR (I%>rateMenuNum%) IF NOT bool% THEN PROCreport(adpcmRateError%) I%=N% ELSE I%-=1 ENDIF =menuList$(rateMenuPtr%+I%) DEFFNwhichIcon(handle%,esg%) SYS"Wimp_WhichIcon",handle%,T%,&003F0000,&00200000 OR (esg%<<16) =!T% DEFPROCSetIcon(handle%,icon%,select%) !Z%=handle% Z%!4=icon% Z%!8=((-select%)<<21) Z%!12=(1<<21) SYS"Wimp_SetIconState",,Z% ENDPROC DEFFNiconSelected(handle%,icon%) !Z%=handle% Z%!4=icon% SYS"Wimp_GetIconState",,Z% =(((Z%!24)AND(1<<21))>0) DEFPROCSelectIcon(handle%,icon%,esg%) LOCAL D% IF esg%>0 THEN SYS"Wimp_WhichIcon",handle%,T%,&001F0000,esg%<<16 ELSE !T%=icon%:T%!4=-1 ENDIF I%=T% D%=Z%+256 WHILE !I%<>-1 !Z%=handle% Z%!4=!I% Z%!8=(-(!I%=icon%))<<21 Z%!12=1<<21 !D%=handle% D%!4=!I% SYS"Wimp_GetIconState",,D% IF ((D%!24)AND(Z%!12))<>(Z%!8) THEN SYS"Wimp_SetIconState",,Z% ENDIF I%+=4 ENDWHILE ENDPROC DEFPROCshade(handle%,bin%,esg%) LOCAL D% D%=Z%+256 SYS"Wimp_WhichIcon",handle%,T%,&001F0000,esg%<<16 I%=T% WHILE !I%<>-1 !Z%=handle%:Z%!4=!I%:Z%!8=((bin%AND1)<<22):Z%!12=(1<<22) !D%=handle%:D%!4=!I%:SYS"Wimp_GetIconState",,D% IF ((D%!24)AND(Z%!12))<>(Z%!8) THEN SYS"Wimp_SetIconState",,Z% ENDIF bin%=bin%>>1 I%+=4 ENDWHILE ENDPROC DEFPROCshadeIcon(handle%,icon%,shade%) !Z%=handle%:Z%!4=icon%:Z%!8=(-shade%)<<22:Z%!12=(1<<22) SYS"Wimp_SetIconState",,Z% ENDPROC REM----------------- Graphics & Sprites DEFPROCLoadWimpSprites LOCAL S$,F$,N%,V%,F% F%=0 S$=dir$+"Sprites" SYS"Wimp_ReadSysInfo",2 TO N%;V% IF (V%AND1)=0 THEN F$=S$+CHR$(N%?0)+CHR$(N%?1) F%=OPENIN(F$) IF F%=0 THEN F$=S$ ENDIF IF F%=0 THEN F%=OPENIN(S$) L%=EXT#F% CLOSE#F% DIM wimpSprites% L%+4 OSCLI("LOAD "+F$+" "+STR$~(wimpSprites%+4)) !wimpSprites%=L% SYS"OS_SpriteOp",256+24,wimpSprites%,"vol" TO ,,volSprite% SYS"OS_SpriteOp",256+24,wimpSprites%,"bar" TO ,,barSprite% SYS"OS_SpriteOp",256+24,wimpSprites%,"tempo" TO ,,tempoSprite% SYS"OS_SpriteOp",512+40,wimpSprites%,barSprite% TO ,,,barWidth% SYS"OS_SpriteOp",512+40,wimpSprites%,volSprite% TO ,,,volWidth% SYS"OS_SpriteOp",512+40,wimpSprites%,tempoSprite% TO ,,,tempoWidth% ENDPROC DEFPROCRangeSprite(sprite%,value,max) REM 2 colour sprite - 1 bit per pixel SYS"OS_SpriteOp",512+40,wimpSprites%,sprite% TO ,,,W%,H% wordWidth%=((sprite%!16)+1)*4 sprite%+=(sprite%!32) mid%=(value*W%)/max FOR I%=0 TO H%-1 FOR J%=0 TO W%-1 STEP 8 IF (J%+8)0 THEN SYS"OS_File",17,pollSpace%+28 TO ,,A% A%=(A%>>8)AND&FFF PROCLoad(A%,pollSpace%+28,(flg%AND4) OR FNwindowOpen(playerWin%),FALSE) ENDIF REM Check the flags in +24 for other operations IF (flg%AND2) THEN loop%=TRUE:PROCLoop ELSE loop%=FALSE:PROCLoop ENDIF PROCSetIcon(playerWin%,playerLoop%,loop%) loopCount%=pollSpace%?25 IF (flg%AND1) THEN PROCPlay ELSE PROCStop(playOn%=FALSE) ENDIF ENDIF WHEN 3,5:REM DataLoad click%=((pollSpace%!16)=5) A%=pollSpace%!40 IF A%>&FFF AND A%<>&3000 THEN IF NOT click% THEN PROCreport(fileTypeError%) ELSE PROCLoad(A%,pollSpace%+44,TRUE,TRUE) ENDIF ENDCASE ENDPROC REM ------------------ Data handling DEFPROCLoad(tempType%,A%,open%,ack%) B%=T% C%=B% WHILE ?A%>0 ?B%=?A% IF ?B%=ASC"." THEN C%=B%+1 B%+=1:A%+=1 ENDWHILE ?B%=13 IF FNCheckLoad(tempType%,C%) THEN $fileBlk%=$T% $fileName%=$C% CASE playType% OF WHEN playWAVE%: IF FNLoadFile(fileBlk%,tempType%,FALSE,TRUE) THEN fileType%=tempType% REM $playerFilePtr%=RIGHT$($fileName%,10):REM 1.37 $playerFilePtr%=RIGHT$($fileName%,16) $playerTitlePtr%=$fileBlk% !Z%=playerWin% PROCCloseWindow(Z%) IF open% THEN PROCOpenWindow(playerWin%,0) ENDIF WHEN playMIDI% REM SYS"NotePad_Init",0 TO A% REM IF A%<(midiMem%*1024) THEN SYS"NotePad_Init",midiMem%*1024 A%=T%+LEN($T%)-1 WHILE ?A%<>ASC"." AND A%>T%:A%-=1:ENDWHILE SYS"XMIDIPlay_File",0,fileBlk%:REM C%,LEFT$($T%,A%-T%+1) SYS"XMIDIPlay_Info" TO midiLen% tempo%=tempoMax%/2 PROCSetTempo(0) posn%=0 PROCSetTimeDisplay PROCSetTime(posn%) PROCGetType(FALSE,TRUE) REM $playerFilePtr%=RIGHT$($fileName%,10):REM 1.37 $playerFilePtr%=RIGHT$($fileName%,16) $playerTitlePtr%=$fileBlk% !Z%=playerWin% PROCCloseWindow(Z%) IF open% THEN PROCOpenWindow(playerWin%,0) dataLoad%=TRUE mtx%=0 ENDCASE IF ack% THEN !(pollSpace%+12)=pollSpace%!8 SYS"Wimp_SendMessage",19,pollSpace%,pollSpace%!20 ENDIF ENDIF ENDPROC DEFFNCheckLoad(type%,file%) LOCAL R%,F% R%=FALSE CASE type% OF WHEN file_WaveForm% R%=TRUE playType%=playWAVE% WHEN file_Armadeus%,file_AudioWrk%,file_ArmMovie%,file_Module% IF NOT click% THEN R%=TRUE:playType%=playWAVE% WHEN file_Riff%,file_Dos% IF NOT click% THEN REM Check header F%=OPENIN($T%) IF F%>0 THEN SYS"OS_GBPB",3,F%,textBlk%,16,0 CLOSE#F% $(textBlk%+16)="RIFF" IF !textBlk%=!(textBlk%+16) THEN $(textBlk%+16)="WAVE" IF !(textBlk%+8)=!(textBlk%+16) THEN $(textBlk%+16)="fmt " IF !(textBlk%+12)=!(textBlk%+16) THEN R%=TRUE playType%=playWAVE% ENDIF ENDIF ENDIF ENDIF ENDIF WHEN file_MIDI% IF midiOn% THEN PROCshadeIcon(playerWin%,playerMenuIcon%,FALSE) PROCshadeIcon(playerWin%,playerRewind%,FALSE) PROCshadeIcon(playerWin%,playerForward%,FALSE) ENDIF playType%=playMIDI% R%=TRUE OTHERWISE IF NOT click% THEN SYS"XOS_ReadVarVal","File$Type_"+STR$~(type%),textBlk%,-1 TO ,,R% IF R%=0 THEN $textBlk%=STR$~(type%AND&FFF) ELSE SYS"XOS_ReadVarVal","File$Type_"+STR$~(type%),textBlk%,256 TO ,,R% ?(textBlk%+R%)=13 ENDIF R%=FNtypeRep(fileTypeLoadError%,$textBlk%,$file%) playType%=playWAVE% ENDIF ENDCASE IF R%=TRUE THEN PROCStop(reset%) CASE playType% OF WHEN playWAVE% IF NOT soundOn% THEN R%=FALSE playType%=playNone% PROCreport(soundNotOnError%) ENDIF WHEN playMIDI% IF NOT midiOn% THEN R%=FALSE playType%=playNone% PROCreport(midiNotOnError%) ENDIF ENDCASE ENDIF =R% DEFFNLoadFile(file%,type%,play%,reset%) LOCAL bool%,handle%,string$,count% LOCAL ERROR ON ERROR LOCAL:IF type%<>armMovie% THEN type%=armMovie%:PROCLoadF(file%,type%,play%,reset%):=TRUE ELSE RESTORE ERROR:PROCSetType:PROCreport(fileLoadError%):=FALSE bool%=TRUE IF type%=armMovie% THEN handle%=OPENIN($file%) FOR count%=1 TO 10 string$=GET$#handle% NEXT CLOSE#handle% IF LEFT$(string$,1)="0" THEN PROCreport(movieNoSoundError%) bool%=FALSE ENDIF ENDIF IF bool% THEN PROCLoadF(file%,type%,play%,reset%) ENDIF =bool% DEFPROCLoadF(file%,type%,play%,reset%) LOCAL A%,B%,C%,D%,E% PROCStop(reset%):REM Un-REMmed in 1.37 to reset sample pointer REM SYS"Hourglass_On":REM 1.37 IF type%=armMovie% THEN oldTime%=-1 SYS"Audio_PlayFile",file%,3+((1+reset%)<<8),,posn%,0 TO ,,,,A% armLen%=A% IF play% THEN playOn%=TRUE PROCSetIcon(playerWin%,playerPlay%,TRUE) ELSE playOn%=-2 ENDIF SYS"Audio_Set" TO sampleRate%,sampleType%,channels%,sampleBits% reversed%=(((channels%>>6)AND1)=1) channels%=channels%AND&F sampleType%-=1 PROCSetTimeDisplay PROCSetTime(posn%) REM Set the options window... $optionsSRatePtr%=STR$(sampleRate%) PROCGetType(FALSE,TRUE) discPlay%=TRUE dataPlay%=FALSE dataLoad%=TRUE ELSE SYS"Audio_LoadFile",file%,type% TO A%,B%,C%,D%,E% sampleRate%=A%:sampleType%=B%:channels%=(C%AND&F):sampleBits%=D%:armLen%=E% reversed%=(((C%>>6)AND1)=1) discPlay%=FALSE $optionsSRatePtr%=STR$(sampleRate%) PROCGetType(FALSE,TRUE) PROCSetTimeDisplay posn%=0 PROCSetTime(posn%) dataPlay%=TRUE discPlay%=FALSE PROCshadeIcon(playerWin%,playerMenuIcon%,FALSE) PROCshadeIcon(playerWin%,playerRewind%,FALSE) PROCshadeIcon(playerWin%,playerForward%,FALSE) dataLoad%=TRUE ENDIF REM SYS"Hourglass_Off":REM 1.37 ENDPROC DEFPROCSetType SYS"Audio_Set",sampleRate%,sampleType%+1,channels%+((-reversed%)<<6),sampleBits% ENDPROC DEFPROCSetTimeDisplay CASE playType% OF WHEN playWAVE%: armTime%=armLen%/((sampleBits%/8)*channels%) A%=armTime%/sampleRate% WHEN playMIDI%: A%=midiLen%/100 ENDCASE M%=A%/60 S%=A%-M%*60 $playerTimePtr%=STR$(M%)+":"+STRING$(2-LEN(STR$(S%)),"0")+STR$(S%) PROCSetIcon(playerWin%,playerTime%,FALSE) ENDPROC DEFPROCMovePlay(D%) LOCAL p% CASE playType% OF WHEN playWAVE% D%=D%*1000 WHEN playMIDI% D%=D%*400 ENDCASE posn%=posn%+D% IF posn%<0 THEN posn%=0 CASE playType% OF WHEN playWAVE% IF posn%>armLen% THEN posn%=armLen% WHEN playMIDI% IF posn%>midiLen% THEN posn%=midiLen% ENDCASE IF playOn% THEN p%=playOn% PROCStop(FALSE) IF p%=TRUE THEN PROCPlay ELSE PROCSetTime(posn%) ELSE PROCSetTime(posn%) ENDIF ENDPROC DEFPROCPlay PROCSendMessage(17,message_PlayStart%) oldTime%=-1 CASE playType% OF WHEN playWAVE% IF discPlay% THEN IF playOn%=-2 THEN playOn%=TRUE ELSE A%=FNLoadFile(playerTitlePtr%,fileType%,TRUE,FALSE) ENDIF ELSE IF dataPlay% THEN SYS"Audio_Play",sampleRate%,posn%,0 ENDIF ENDIF IF (discPlay% AND (playOn%=TRUE)) OR dataPlay% THEN PROCSetTimeDisplay PROCSetTime(posn%) PROCSetIcon(playerWin%,playerPlay%,TRUE) playOn%=TRUE ENDIF WHEN playMIDI% SYS"XMIDIPlay_Start",0,posn% PROCSetIcon(playerWin%,playerPlay%,TRUE) playOn%=TRUE ENDCASE ENDPROC DEFPROCStop(reset%) loopCount%=0 PROCSendMessage(17,message_PlayStop%) IF dataLoad% AND reset% THEN oldTime%=-1 posn%=0 PROCSetTimeDisplay PROCSetTime(posn%) ENDIF CASE playType% OF WHEN playWAVE% SYS"Audio_Stop" IF pause% THEN SYS"Audio_Pause",0 pause%=FALSE PROCSetIcon(playerWin%,playerPause%,FALSE) ENDIF IF mute% THEN SYS"Audio_Mute",0 mute%=FALSE PROCSetIcon(playerWin%,playerMute%,FALSE) ENDIF WHEN playMIDI% SYS"XMIDIPlay_Stop" IF pause% THEN pause%=FALSE PROCSetIcon(playerWin%,playerPause%,FALSE) ENDIF IF mute% THEN mute%=FALSE PROCMute PROCSetIcon(playerWin%,playerMute%,FALSE) ENDIF ENDCASE playOn%=FALSE PROCSetIcon(playerWin%,playerPlay%,FALSE) ENDPROC DEFPROCLoop IF playType%=playWAVE% THEN IF loop% SYS"Audio_Loop",1 ELSE SYS"Audio_Loop",0 ENDIF ENDPROC DEFPROCPause CASE playType% OF WHEN playWAVE% IF pause% SYS"Audio_Pause",1 ELSE SYS"Audio_Pause",0 WHEN playMIDI% IF pause% THEN SYS"XMIDIPlay_Stop" ELSE SYS"XMIDIPlay_Start",1 ENDIF ENDCASE ENDPROC DEFPROCMute CASE playType% OF WHEN playWAVE% IF mute% THEN SYS"Audio_Mute",1 ELSE SYS"Audio_Mute",0 WHEN playMIDI% IF mute% THEN PROCSetMIDIVolume(0,FALSE) ELSE PROCSetMIDIVolume(midiVolume%,FALSE) ENDIF ENDCASE ENDPROC DEFPROCSetVolume(V%) IF V%<0 THEN IF V%=-1 THEN V%=currentVolume%-1+shift%*9 ELSE IF V%=-256 THEN V%=currentVolume%+1-shift%*9 ENDIF ENDIF IF V%<0 THEN V%=0 IF V%>volMax% THEN V%=volMax% PROCRangeSprite(volSprite%,V%,volMax%) !T%=playerWin%:T%!4=playerVolBar%:T%!8=0:T%!12=0 SYS"Wimp_SetIconState",,T% currentVolume%=V% CASE playType% OF WHEN playWAVE%: SYS"Audio_Volume",V% WHEN playMIDI%: PROCSetMIDIVolume(V%,TRUE) ENDCASE ENDPROC DEFPROCSetMIDIVolume(V%,T%) IF T% THEN midiVolume%=V% IF V%<=0 THEN V%=1 SYS"XMIDIPlay_Volume",(V%*2)-1 ENDPROC DEFPROCcheckLoopCount IF loopCount%>0 THEN loopCount%-=1 IF loopCount%=0 THEN loop%=FALSE PROCLoop PROCSetIcon(playerWin%,playerLoop%,loop%) ENDIF ENDIF ENDPROC DEFPROCSetTime(V%) LOCAL M%,S%,A% CASE playType% OF WHEN playWAVE% IF (V%/sampleRate%)(V%/sampleRate%) THEN PROCRangeSprite(barSprite%,V%/sampleRate%,armTime%/sampleRate%) !T%=playerWin%:T%!4=playerTimeBar%:T%!8=0:T%!12=0 SYS"Wimp_SetIconState",,T% oldTime%=V%/sampleRate% ENDIF A%=V%/sampleRate% WHEN playMIDI% REM PROCe("V%="+STR$(V%)+" midiLen%="+STR$(midiLen%)) IF (V%/500)(V%/1000) THEN PROCRangeSprite(barSprite%,V%/1000,midiLen%/1000) !T%=playerWin%:T%!4=playerTimeBar%:T%!8=0:T%!12=0 SYS"Wimp_SetIconState",,T% oldTime%=V%/500 A%=V%/100 ENDIF ENDCASE M%=A%/60 S%=A%-M%*60 REM PROCe("Minutes = "+STR$(M%)+" Seconds = "+STR$(S%)) IF rcode% THEN IF NOT playOn% THEN SYS"RealTime_Control",2,-1,0,0,(M%<<8)+S% ENDIF ENDIF ENDPROC DEFPROCSetTempo(V%) LOCAL V,M%,A% REM PROCe("Set tempo = "+STR$(V%)) V%=tempo%+V% IF V%<0 THEN V%=0 IF V%>tempoMax% THEN V%=tempoMax% PROCRangeSprite(tempoSprite%,V%,tempoMax%) !T%=MControlWin%:T%!4=MControlTempoBar%:T%!8=0:T%!12=0 SYS"Wimp_SetIconState",,T% tempo%=V% M%=tempoMax%/2 V=4^(tempo%/M%-1) SYS"XMIDIPlay_Tempo",V*(1<<8) ENDPROC REM -------------- Utilities DEFFNstring(S%) LOCAL S$ WHILE ?S%<>0 S$=S$+CHR$(?S%) S%+=1 ENDWHILE =S$ REM -------------- Messages DEFPROCSendMessage(mesg%,type%) !messageBlk%=24 messageBlk%!4=0 messageBlk%!8=0 messageBlk%!12=0 messageBlk%!16=messageBase% messageBlk%!20=type% REM SYS"Wimp_SendMessage",mesg%,messageBlk%,0 ENDPROC REM ---------------- Initialising routines DEFPROCStartWimp taskName$="ESP MIDI/sample player" appName$="!Player" dir$="." $Z%="TASK" $(Z%+4)=taskName$+CHR$(0) SYS"Wimp_Initialise",200,!Z%,Z%+4 TO vers%,taskHandle% !Z%=-1:Z%!4=40:Z%!8=0:Z%!12=140:Z%!16=80:Z%!20=&301A $(Z%+24)=appName$ SYS"Wimp_CreateIcon",,Z% TO ihandle% ENDPROC DEFPROCMakeDims DIM Z% 4000 DIM T% 256 DIM pollSpace% 1000 DIM messageBlk% 256 wlen%=4000 DIM wdata% wlen% DIM fileBlk% 256 DIM fileName% 256 DIM textBlk% 256 DIM msgBlk% 16 DIM menuBlk% 2000 DIM menuText% 2000 DIM bit$(4) DIM message$(6) DIM sampName$(5) oldRateNum%=21:DIM oldRates%(oldRateNum%) oldRates%()=5000,6250,6944,7812,8928,10416,11025,11363,12500,13888,15625,17857,20833,22050,25000,27777,31250,35714,41666,44100,50000 ENDPROC DEFPROCSet signedLin%=0:sampName$(0)="Signed" unsignedLin%=1:sampName$(1)="Unsigned" arcLog%=2:sampName$(2)="Arc" adpcm%=3:sampName$(3)="ADPCM" mono%=1:sampName$(4)="Mono" stereo%=2:sampName$(5)="Stereo" pause%=FALSE loop%=FALSE mute%=FALSE reversed%=FALSE armMovie%=&AE7 playOn%=FALSE armLen%=0 oldTime%=0 posn%=0 discPlay%=FALSE dataPlay%=FALSE dataLoad%=FALSE file_ArmMovie%=&AE7 file_data%=&FFD file_Armadeus%=&D3C file_AudioWrk%=&BD6 file_WaveForm%=&FB1 file_Riff%=&BF7 file_Dos%=&FE4 file_Module%=&FFA file_Data%=&FFD file_MIDI%=&FD4 dragVolume%=0 dragTime%=1 dragTempo%=2 dragOn%=FALSE playNone%=0 playMIDI%=1 playWAVE%=2 playType%=playNone% midiMem%=511 SYS"OS_ReadVarVal","Player$Sound",Z%,256 soundOn%=(?Z%=49) SYS"OS_ReadVarVal","Player$MIDI",Z%,256 midiOn%=(?Z%=49) volMax%=128 currentVolume%=volMax% midiVolume%=volMax% tempoMax%=1000 tempo%=tempoMax%/2 messageBase%=&4DC00 message_PlayStart%=1 message_PlayStop%=0 message_PlayFile%=&100 PROCCheckSound16 ENDPROC DEFPROCCheckSound16 SYS &60144,0 TO sound16% :REM "Sound_Mode" IF sound16%=1 THEN sound16%=TRUE ENDPROC DEFPROCLoadWindows LOCAL W$,str% W%=wdata% $T%=dir$+"Templates" SYS"Wimp_OpenTemplate",,T% $T%="Player,Options,Info,MControl" str%=T%:L%=str%+LEN($T%) REPEAT I%=INSTR($str%,",") IF I%>0 THEN W$=LEFT$($str%,I%-1) ELSE W$=$str% R%=Z% SYS"Wimp_LoadTemplate",,R%,W%,wdata%+wlen%,0,W$,0 TO ,,W%,,,,H% REM PROCee("used:"+STR$(W%-wdata%)) IF H%=0 THEN PROCee("Window not found") ELSE P%=R%+88+20 CASE W$ OF WHEN "Player": R%!64=wimpSprites% playerTitlePtr%=!(R%+72) playerFileName%=11 playerFilePtr%=!(P%+playerFileName%*32) playerTimeBar%=9 playerTime%=15 playerTimePtr%=!(P%+playerTime%*32) playerDescription%=16 playerDescPtr%=!(P%+playerDescription%*32) playerVolBar%=4 playerStop%=5 playerPlay%=2 playerPause%=3 playerRewind%=13 playerForward%=12 playerCount%=15 playerCountPtr%=!(P%+playerCount%*32) playerLoop%=10 playerMenuIcon%=17 playerMute%=14 playerVolLeft%=8 playerVolRight%=7 muteESG%=2 WHEN "Options": R%!64=wimpSprites% optionsTypeESG%=3 optionsSignedLin%=4 optionsSignedLinText%=!(P%+optionsSignedLin%*32) optionsUnsignedLin%=5 optionsUnsignedLinText%=!(P%+optionsUnsignedLin%*32) optionsArcLog%=6 optionsArcLogText%=!(P%+optionsArcLog%*32) optionsADPCM%=7 optionsADPCMText%=!(P%+optionsADPCM%*32) optionsChannelsESG%=2 optionsMono%=13 optionsMonoText%=!(P%+optionsMono%*32) optionsStereo%=14 optionsStereoText%=!(P%+optionsStereo%*32) optionsReversed%=12 optionsReversedText%=!(P%+optionsReversed%*32) optionsBitsESG%=1 optionsBits4%=8 optionsBits8%=9 optionsBits12%=10 optionsBits16%=11 optionsSampleRate%=18 optionsSRatePtr%=!(P%+optionsSampleRate%*32) optionsSRateUp%=16 optionsSRateDown%=17 optionsRateMenu%=20 optionsOK%=22 optionsCancel%=21 WHEN "Info": $(!(P%+4*32))=v$+d$ WHEN "MControl" R%!64=wimpSprites% MControlTempoBar%=2 MControlTempoLeft%=3 MControlTempoRight%=4 MControlText%=8 MControlTextPtr%=!(P%+MControlText%*32) ENDCASE SYS"Wimp_CreateWindow",,R% TO H% CASE W$ OF REM Store handle WHEN "Player":playerWin%=H% WHEN "Options":optionWin%=H% WHEN "Info":infoWin%=H% WHEN "MControl":MControlWin%=H% ENDCASE ENDIF str%+=LEN(W$)+1 UNTIL str%>=L% SYS"Wimp_CloseTemplate" ENDPROC REM ------------------------ Menu handling DEFPROCDecodeMenu(blk%) CASE menu% OF WHEN iconM%: IF !blk%=1 THEN quit%=TRUE WHEN rateM%: PROCRateChange(-1,VAL(menuList$(rateMenuPtr%+(blk%!4)+1)),0) !Z%=optionWin%:SYS"Wimp_GetWindowState",,Z% SYS"Wimp_CreateMenu",,optionWin%,Z%!4,Z%!16 ENDCASE ENDPROC DEFPROCLoadMenus DIM menuList$(30) M%=0:mcount%=0 PROCOpenMessage iconM%=mcount%:mcount%+=1 iconMenuNum%=2 iconMenuPtr%=M%:M%+=(iconMenuNum%+1) FOR I%=0 TO iconMenuNum% PROCGetToken("iconM"+STR$(I%)) CASE I% OF WHEN 1:out$+=">"+STR$(infoWin%) ENDCASE menuList$(iconMenuPtr%+I%)=out$ NEXT rateM%=mcount%:mcount%+=1 IF soundOn% AND sound16% THEN SYS"Sound_SampleRate",0 TO ,rateMenuNum% ELSE rateMenuNum%=oldRateNum% ENDIF rateMenuPtr%=M%:M%+=(rateMenuNum%+1) PROCGetToken("rateM0") menuList$(rateMenuPtr%)=out$ FOR I%=1 TO rateMenuNum% IF soundOn% AND sound16% THEN SYS"Sound_SampleRate",2,I% TO ,,A% ELSE A%=oldRates%(I%-1)<<10 ENDIF menuList$(rateMenuPtr%+I%)=STR$(A%>>10) NEXT FOR I%=1 TO 3 PROCGetToken("Bit"+STR$((I%+1)*4)) bit$(I%)=" "+out$ NEXT PROCGetToken("Report0") fileTypeError%=0 message$(0)=out$ PROCGetToken("Report1") fileTypeLoadError%=1 message$(1)=out$ PROCGetToken("Report2") sampleRateError%=2 message$(2)=out$ PROCGetToken("Report3") adpcmRateError%=3 message$(3)=out$ PROCGetToken("Report4") movieNoSoundError%=4 message$(4)=out$ PROCGetToken("Report5") soundNotOnError%=5 message$(5)=out$ PROCGetToken("Report6") midiNotOnError%=6 message$(6)=out$ PROCCloseMessage fileLoadError%=7 ENDPROC DEFPROCOpenMenu(menuPtr%,menuNum%,num%,X%,Y%) menu%=num% M%=menuBlk%:K%=menuText% $M%=LEFT$(menuList$(menuPtr%),12) W%=LEN($M%) M%!12=&00070207 M%!20=44 M%!24=0 M%+=28 FOR I%=1 TO menuNum% !M%=-&80*(I%=menuNum%) P%=INSTR(menuList$(menuPtr%+I%),">") IF P%>0 THEN $K%=LEFT$(menuList$(menuPtr%+I%),P%-1) $T%=RIGHT$(menuList$(menuPtr%+I%),LEN(menuList$(menuPtr%+I%))-P%) P%=VAL($T%) ELSE $K%=menuList$(menuPtr%+I%) P%=-1 ENDIF M%!4=P% M%!8=&7000111 M%!12=K% M%!16=K%+LEN($K%) M%!20=LEN($K%) IF LEN($K%)>W% THEN W%=LEN($K%) K%+=LEN($K%)+1:M%+=24 NEXT menuBlk%!16=(W%+1)*16 IF num%=rateM% THEN SYS"Wimp_CreateSubMenu",,menuBlk%,X%-64,Y% ELSE SYS"Wimp_CreateMenu",,menuBlk%,X%-64,Y% ENDIF ENDPROC REM -------------- Real Time control --------------------- DEFFNCheckRealTime SYS "XOS_SWINumberFromString",,"XRealTime_Install" TO I% ; f% IF f% AND 1 THEN=FALSE =TRUE LOCAL ERROR ON ERROR LOCAL:RESTORE ERROR:=FALSE OSCLI("RMEnsure RealTime 0.01 Error Module not found") =TRUE REM ------------------------ Messages DEFPROCOpenMessage $fileBlk%=dir$+"Messages" SYS"MessageTrans_FileInfo",,fileBlk% TO F%,,S% IF (F% AND 1) = 0 THEN mbuf%=Z% SYS"MessageTrans_OpenFile",msgBlk%,fileBlk%,mbuf% ENDPROC DEFPROCGetToken(token$) SYS"MessageTrans_Lookup",msgBlk%,token$,T%,256,0,0,0,0 TO ,,out$ ENDPROC DEFPROCCloseMessage SYS"MessageTrans_CloseFile",msgBlk% ENDPROC REM ------------------------ Error routines DEFPROCError CLOSE #0 !Z%=ERR $(Z%+4)=REPORT$+" at line "+STR$(ERL)+CHR$(0) SYS"Wimp_ReportError",Z%,1,taskName$ TO ,R% ENDPROC DEFPROCErr PROCError END ENDPROC DEFPROCreport(mnum%) !Z%=0 IF mnum%=fileLoadError% THEN $(Z%+4)=REPORT$+CHR$(0) ELSE $(Z%+4)=message$(mnum%)+CHR$(0) ENDIF SYS"Wimp_ReportError",Z%,1,taskName$ TO ,R% ENDPROC DEFFNtypeRep(N%,P1$,P2$) LOCAL T%,F% T%=INSTR(message$(N%),"%1") F%=INSTR(message$(N%),"%2") !Z%=0 $(Z%+4)=LEFT$(message$(N%),T%-1)+P1$+MID$(message$(N%),T%+2,F%-T%-2)+P2$+RIGHT$(message$(N%),LEN(message$(N%))-(F%+1))+CHR$(0) SYS"Wimp_ReportError",Z%,3,taskName$ TO ,R% =(R%=1) DEFPROCee(M$) LOCAL Q% VDU4:PRINTTAB(0,1);M$;:REPEAT:Q%=GET:UNTIL Q%=32 OR Q%=27:PRINTTAB(0,1);SPC(LEN(M$));:VDU5: IF Q%=27 THEN END ENDPROC DEFPROCe(M$):VDU4:PRINTTAB(0,1);SPC(LEN(M$)+2);TAB(0,1);M$;:VDU5:ENDPROC