DOCS.109 )pJJJJ K ' M ' LG &PRODOS $?EGv FjJJ S8 m DOCS.109 METAL.DOCS FINDER.DATA METAL.DOCS '.ACOSMETAL.XLAT )AGREEMENT *COMM.TYPES .COMMANDS.BURST ,COMMANDS.P.A ,COMMANDS.P.B ,COMMANDS.P.C ,COMMANDS.P.D ,COMMANDS.P.E ,COMMANDS.P.F ,COMMANDS.P.G ,COMMANDS.P.H ,COMMANDS.P.I ,COMMANDS.P.L ,COMMANDS.P.M ,COMMANDS.P.N ,COMMANDS.P.O ,COMMANDS.P.P ,COMMANDS.P.Q ,COMMANDS.P.R ,COMMANDS.P.S ,COMMANDS.P.T ,COMMANDS.P.U ,COMMANDS.P.V ,COMMANDS.P.W ,COMMANDS.P.X /COMMANDS.P.0ETC ,CONFIG.COMMS 'DEVICES *FILE.TYPES *INSTALLING *LOCAL.KEYS -METAL.DOSERRS -METAL.SYSERRS ,SOFT.LICENSE /THE.METAL.FILES +FINDER.DATA O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<=== O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<=== handled by bbs code, no built-in commands DThe following is a quick and dirty "cross reference" that will give I Gyou a rough idea of converting Acos "segments" over to Metal "modules" F D(the name "segments" and "modules" are interchangeable and mean the H Fsame thing - source files for the BBS program). Note that this is NOT I Gofficial, and neither L&L nor Wilson Wares endorse this file. Use this information at your own risk. Metal uses "!" to flag a comment line, Acos uses ";" -- Acos comment: ; this is a comment Metal comment: ! this is a comment FNote that Metal allows you to put a comment anywhere in a line, not just at the first character. Metal allows a 31-character limit on labels, Acos has a limit of 8. Metal has a 4-character limit on variables, Acos has a limit of 2. GMetal defines a "global" or "public" label when the label is defined - : Acos defines a "public" label using a different command: Acos public/global syntax: public label Metal public/global syntax: label global FAcos allows you "loose" the second double-quote mark on a line - just ? like AppleSoft. Metal, however, requires you to close it off. Acos legal syntax: print "Hi Metal legal syntax: print "Hi" GNote that both Acos and Metal, when using the single-quote mark ("'"), F Dact just the same in that there must be two of them - one to start, one to stop. FAcos has a single clock timer; Metal has 4, with a fifth one used for # waiting for a key (idle timeout). EAcos will only allow you to create text files (filetype of 4), while H FMetal will allow you to create any filetype, and DEFAULTS to creating & a sub-directory (like Basic.System). DAcos's GET command defaults to no case conversion, echo back. Metal F Ddefaults to lower case shifted to upper case, echo back. Metal also A ?allows you to re-defined the default Get mode via the compiler > directive ".defmode get x", where x is the new default mode. Acos Syntax Metal Syntax ADDINT(string$) ABORT$==+string$) APPEND no change) BYTE no change) CHR$(char) no change2 CHR$(char,rep) REPEAT$(char$,rep)) CLEAR no change7 CLOCK(0) CLOCK(1); (2); (3); (4)? CLOCK(1) CLOCK(1,2); (2,2); (3,2); (4,2)? CLOCK(2) CLOCK(1,1); (2,1); (3,1); (4,1)) CLOSE no change% COPY TCOPY. CREATE file$ CREATE file$,4D CRUNCH handled by bbs code, no built-in commands; DATE$ no change, may only be read4 ECHO=string$ input ([string$])...) ECHO="" don't useH EDIT handled specially - see the EDIT command) no change< FILL start,len,data MCLEAR start TO data FOR len# FLAG BIT) no change) FREE no change+ GET MODE(2)) GOSUB no change) GOTO no change) HOME CLEAR VID) no change3 INFO SYSINFO, VID, MODEM/ INPUT default INPUT MODE("N")7 INPUT @0 INPUT MODE("UN") LEN(1)1 INPUT @1 INPUT MODE("UN,")/ INPUT @2 INPUT MODE("U")% INPUT @3 INPUT7 INSTR(find$,search$) INSTRING(find$,search$)' SYSINFO, KILL file$ DELETE file$) LEFT$ no change) no change# LINK RUN- LOG path$ PREFIX$=path$( MARK FILEMARK) MID$ no changeC MODEM(0) MODEM(1)=0 ?????C MODEM(1) MODEM(1)=1 ?????C MODEM(2) MODEM(1)=2 ?????; MOVE start,len TO targ MCOPY start TO targ FOR lenD SMF_commands - see SMF_xxxx commands) NEXT no change) NIBBLE no change) no change, ON NOCAR TRAP MODEM=6) OPEN no change& PADDLE) PEEK no change) POKE no change) no change) POSITION no change- PRINT @x,y PRINT AT(x,y), PUBLIC label label GLOBAL) PUSH no change- special setup- RAM2 special setup? RANDOM(x) no change, result is 0 to (x-1)% READ BLOAD( READY SMF_OPEN& RECALL filename$ UNHIDE) RETURN no change@ REWIND handled by combo of SMF_commands) RIGHT$ no change3 RND$ CHR$(RANDOM(26)+65)> SET string$=memloc,len MEMSTRING$(memloc,len)=string$> string$=MEMSTRING$(memloc,len). SETINT(string$) ABORT$=string$$ STORE filename$ HIDE) STR$ no change) TEXT no change) THEN no change) TIME$ no change5 TONE(pitch,dur) PLAYTONE(dur,pitch,0)% UPDATE FLUSHE EXT [different load/run address]) no change# WHEN$ n/a# WIDTH n/a% WRITE BSAVE FNote that the channel numbers/devices numbers are different - devices H F0, 1, and 2 act the same between Metal and Acos, but after that, they differ. AAcos returns a Random number from 1 to x; Metal returns a random number from 0 to (x-1). FMetal uses a different "message" file structure - SMF (Single Message G EFormat) files, which actually allow non-text files to be stored. See the section on SMF commands. BAcos tones and Metal tones will not sound the same using the same 9 values - they are, of course, using different routines. !"#$ O==<==<====<====<====<====<====<====<====<====<====<====<====<====<====<====<=== O==<==<====<====<====<====<====<====<====<====<====<====<====<====<====<====<=== )Has no effect for the FullScreen Editor. Metal : Agreement of Software Purchase Page Agreement of Software purchase When you bought the Metal and Future Vision package, you also got an H Fundeclared agreement between you and Wilson Wares. Most of these were N Lobvious and didn't need stated, but some weren't. Like any business, Wilson H Wares has certain rules that govern the way it handles sales and such. 1. Upgrades Upgrading of the Metal language and the Future Vision BBS program are done in the following manner: You must have an active account on The Captain's Quarters BBS (614) K I488-8401. This account must contain your current voice (or home) phone $ number and your mailing address. In order to get upgrades, you simply call the BBS and download them. N LSimple and effective. This puts all the upgrading on you, of course, but it % does have the following advantages: a) you get the upgrades quickly - generally, it takes about 5 minutes to N Ldownload a complete new version of Metal, and about 20-30 for Future Vision (assuming 2400 baud)M b) you don't have to wait for the US Postal Service to ship the disk and N Lhave it turn out to be faulty when you get it (one of the major reasons for doing it this way).M c) it's ecologically good, since we don't have to ship out a whole bunch 0 of disks that you will just toss away anyways. 2. Upgrading to Metal GS Within the next few months (a target date of December 1991), Metal GS will M Kbecome available for $95.00. Users who already have purchased Metal before G EMetal GS becomes available will be able to upgrade (re: download the P Nsoftware) with no extra charge . Users who purchase after Metal GS becomes M avail will be able to upgrade from Metal-8 to Metal GS for a $20 surcharge. 3. Serial numbers and support Each person who purchases Metal gets a personal serial number that is M K"burned" into the program. This serial number is used to keep track of who ( has what version and when they got it. 4. Transference of software There may come a time when you decide that you no longer want Metal and L Jwish to sell your copy to someone else. Doing so is possible and requires $ that you take the following steps: a) contact the sysop of The Captain's Quarters BBS (614) 294-0556 and E Cnotify him that you are transferring the software to someone else. I GInclude the name, phone number, and address of the person that you are transferring the software to.A b) that person must then log onto the BBS and get an account.O c) once the information is gotten, that person must pay a $25 surcharge to transfer the software.N d) once the software has been transferred, you must delete your copy, and K Iyou will no longer receive access or support to the Metal section of the BBS. 5. Pirating and Illegal copies. Let's face it, people are going to pass the software around. We all do it. $ It's a fact of life. But consider: It took over two years to write Metal and Future Vision for what is O Mconsidered a "dead" series of equipment. Compared to the other BBS languages O and programs out on the market, Metal is the cheapest and the most developed. However, good ideals and such nonwithstanding, there will be people who J will pass the program around. Thus the following rules will be enforced: a) if you pass the Metal software around (re: pirate) and word gets back J Hto Wilson Wares, you are under immediate support suspension. This means J your account will not be able to get into the Metal areas of the system.J b) if it does turn out that you have let the software out, you will Iloose access to Metal support, and if you are in the Future Vision H FNetwork, your site will be removed from the list. These two actions E Cwill become permanent , and a notification will go out across the I Gnetwork informing the others of your actions (thus your good name will ! become mud, in layman's terms). &'()*+,-./012 O==<===============<======<===================================================== O==<===============<======<===================================================== Metal In General : Command Types Metal In General : Command Types Page Metal Command Types KThe following is a list of each command type and an explanation of what is meant for each one. type explanation& ----------------------- ----------- Kboolean math operand Boolean math operands perform bit-level functions 4 2on the preceding and following numerical data and 1 /returns a bit-level value back. These function - +somewhat similar, but then again, somewhat ! different from math operands. Kburied command Buried Commands are simply command words that are 3 1used as "place holders" to signify to Metal that 6 4certain types of data follow. For example, a common 4 2Buried Command is the word "TO", which is used in several commands, like this:" for j = 1 TO 9" tcopy #1 TO #2. mcopy ram TO ram+32 for 32L Some commands have the Buried Command type along 3 1with other types - these command words serve two 5 3purposes: they function as legitimate commands and " as Buried Commands. For example: UNTIL x=9, tcopy #1 UNTIL "--" Gcommand Commands are the basic building blocks of any 3 1interpreted language, and Metal is no exception. . ,There is a difference between "Command" and 5 3"Command Word" - a "Command" is the first executed / command word in a line or command definition:( PRINT "Hello":RETURN) IF j=1 then GOTO exitM In these examples, PRINT is a Command - it is the 3 1first command word in the line. RETURN is also a 7 5Command - it is the first command word following the 6 4colon separator. The IF and GOTO commands words are 6 4Commands - the IF is, of course, the first Command, 2 0and the GOTO is the first command following the buried command "then". Kcompiler directive A compiler directive is a word or symbol that the 5 3compiler processes specially, which may or may not 3 1result in something being placed in your runtime 5 3program. Compiler directives generally force the 6 4compiler to do something - like generating a label, 3 1adding additional source files to the first one, 3 ending compilation before the end of a file, etc. Icomplex command A complex command is one that has more than one 6 4result, based on the data it is given. For example, 6 4GOTO is relatively simple command - it just changes 4 2where the program is running; however, INPUT is a 4 2very complex command - you can specify everything . ,from where to get the input data from, what 6 4variables to put it into, the maximum length of the 2 0data, what sort of filter operation to perform, 7 5wether or not to echo the data back to the typist or - +use some sort of string, different kind of 7 5prompting, and what type of character separates each data piece (whew!) Mcomplex system value A complex system value is similar to a system value 4 2in that you may only read the value, not change 5 3it. However, the result returned depends both upon 2 0the current program state, and the value of the / -function given the complex system value. For 5 3example, the SYSINFO command word always returns a / -number, but depending on the value given the 6 4SYSINFO, you can pull out numbers that reflect upon 4 2how many keys are in the input buffer to how many errors Metal has had happen. Lcomplex system variable Complex system variables are similar in concept to 3 1both system variables and complex system values. 1 /However, unlike complex system values, complex 6 4system variables be changed by the program by equating them to some value. Lflow command Flow commands are those commands that change where 5 3the program is executing at. These range from such - +simple commands as GOTO to more elaborate, # multi-nested LONG IF expressions. Hlogic operand Logic functions are simply math functions that 7 5return a value of 0 (false) or 1 (true). These range 7 5from common commands as the equals ("=") sign, which 2 0simply compares two values and returns a 0 (not 4 2equal) or 1 (was equal) to the EOR function which ! does odd functions on the data. Flooping command The looping commands are similar to the flow 5 3commands in that they can change where the program 5 3executes, but they do this based on given data and use labels. Mmath function Math functions are commands that return a numerical 7 5value based on a given set of data. For example, ABS - +and INSTRING are both math functions - the 6 4difference is that ABS functions on numerical data, 7 5while the INSTRING functions on two pieces of string data. Mmath operand A math operand is one that takes the preceding data 3 1and uses it with the following data and performs 5 3some function upon it. For example 1+3 will result in a value of 4 (of course). Lstring function A string function is quite similar in concept as a 7 5math function, it just returns a string instead of a number. Gstring operand A string operand, again, is similar to a math 0 .operand, in that is operates on preceding and 4 following string data, and returns a string value. Isystem value A system value is a command that just returns a 4 2constant or changing data value or string result. 3 1You may set these to some result - you may / only read out the current value from these. Lsystem variable A system variable is a command that functions like 5 3a system value, but you may also set these to some 4 2value, which generally results in a change in the 6 4way that Metal operates. For example, RECNUM, which 6 4either returns the current record being used in the 6 4file, or allows you to change the current record in & the file, is such a system variable. 456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<=== O===========================================================================>=== .DEFSTR0="string" Metal In General : Command Quick Reference Page Short and Sweet Metal Command Quick Reference MThe following is a list of each command, with syntax format, and the type of J Hcommand that each one falls under. Text within the curly braces { } are ) optional parameters for the commands. O===========================================================================>===N command name command type(s)N ------------ ---------------N ABORT$ system variableN =ABS(number) math functionN ADDR{area}{(index)} complex system variableN ALLOCATE(num,len{,start}) commandN =x AND y logic operandN APPEND #device commandN =ASC(char$) math functionN print AT(x,y) buried command =x B.AND y boolean math operandN =x B.EOR y boolean math operandN =x B.OR y boolean math operandN BIT{area}{(index)} complex system variableN =BITSTR$(value{,len{,flag}}) string functionN =BITVAL(string$) math functionN BLOAD #device,memloc,length commandN BSAVE #device,memloc,length commandN BYTE{area}{(index)} complex system variable CALL address{,options} complex commandN CALL shell$,bitpointer,stafflevel complex commandN =CHR$(number) string functionN CLEAR {extender} complex commandN CLOCK(func{,opt}) complex system variable/commandN CLOSE {#device} commandN =CNGCASE$(string$,function) string functionN COMPILE filename$ {MODE(function)} commandN CR{(number)} buried commandN =CR$ string functionN CREATE filename${,filetype{,auxtype}} command =DATE$ system valueN =DAYNUM{(date${,1})} system valueN DEALLOCATE(num) commandN DELETE filename$ commandN DEVICE system variableN DO command(s) looping commandN =DOSERR system value EDIT(num) complex system variable/commandN EDIT$(index) system variableN ELSE buried commandN END {extenders} complex commandN =x EOR y logic operandN =ESC$ string functionN EXT filename$ or #package {,opts} complex command FCOPY sourcefile$ or #device TO targetfile$ or #device command# {MODE(option)} {LEN(bytes)}N FILENAME$(device or string${,type}) system valueN FILEACCESS(filename$ or device) system variableN FILEAUXTYPE(filename$ or device) system variableN =FILEINFO$(filename$) system valueN FILEMARK(device) system variableN FILESIZE(device or filename$) system variableN FILETYPE(filename$ or device) system variableN FLUSH {#device} commandN FOR var = start TO stop {STEP stepval} looping commandN FREE commandN =FREE{(slot,drive) or (filename$)} system value GET {#device} {MODE(func)} variable commandN GOSUB label flow commandN GOTO label flow command =HEXSTR$(num{,len{,1}}) string functionN =HEXVAL(string$) math functionN HIDE {RETURN} command IF condition {THEN} commands {ELSE commands} logical flow commandN INPUT {#device} {MODE(string$)} {[allow$]} {LEN(len)} complex command: {"prompt"} {CR} {(string$ prompt)} {([echoback$])}0 variable {TO{,}} {, or CR} {variable(s)}N =INSTRING(find$,search${,wild$}) math function =LEFT$(string$,length) string functionN =LEN(string${,option}) math functionN LONG IF condition logical flow command MAKEWORKFILE(return${,dir$}) commandN MCLEAR start TO value8bit FOR length commandN MCOPY source TO target FOR length commandN =MEMAREA(num) system valueN =MEMSIZE(num) system valueN MEMSTRING$(memloc{,length}) command/string functionN =MID$(string$,index{,length}) string functionN =x MOD y math operandN MODE(func) buried commandN MODEM$ system commandN MODEM(func) complex system variable =x NAND y logic operandN =x NEOR y logic operandN NEXT {variable} looping command/2nd part of FORN NIBBLE{area}{(index)} complex system variableN =x NOR y logic operandN =NOT y logic operand ON value GOTO/GOSUB/PUSH label1{,label2{,etc}} commandN =ONLINE$(slot,drive) system valueN OPEN #device,filename$ commandN =x OR y logic operand =PADDLE(number) math functionN =PEEK(memloc) math functionN =PEEKADDR(memloc) math functionN =PEEKBYTE(memloc) math functionN =PEEKWORD(memloc) math functionN PLAYTONE (duration,startone{,toneadditive)} commandN =PERCENTAGE(x,y) math functionN POKE memloc,value commandN POKEADDR memloc,value commandN POKEBYTE memloc,value commandN POKEWORD memloc,value commandN POP {extender} complex flow commandN POSITION {#device,} recnum{,reclen{,byteoffset}} commandN PREFIX${(pathnum)} system variableN PRINT {#device} {AT (x,y)} {string$ expression} complex command@ {numerical expression} {"literal text"} {literal number}= {variable} {TO{,}} {CR{(times}} {TAB(to_pos{,char$})}' {REPEAT$(string,times)} {,} {;}N PRINTER buried commandN PULLVAR variable{,variable{,variable...}} commandN PUSH label flow commandN PUSHVAR value{,value{,value...}} command QUIT {TO filename$} command =RANDOM(range) math functionN RECNUM(device) system variableN RENAME oldfilename$,newfilename$ commandN =REPEAT$(string$,times) string functionN RETURN flow command/2nd part of GOSUBN =RIGHT$(string$,length) string functionN =ROTL(value) math functionN =ROTR(value) math functionN RUN filename${,global$} flow commandN RUNSUB filename${,global$} flow commandN RUNRETURN flow command =SIGN(value) math functionN SMF_ALLOCATE(channel,number,size) commandN SMF_ATRIB(channel,number) system variableN SMF_CLOSE(channel) commandN SMF_CREATE(filename$,number) commandN SMF_DELETE(channel,number{,count}) commandN SMF_FLUSH(channel) commandN =SMF_INFO(channel,number) system valueN SMF_OPEN(channel,filename$) commandN SMF_READ(channel,number,filename$) commandN SMF_REMOVE(channel,number) commandN =SMF_SIZE(channel,number) system valueN SMF_USER(channel,number) system variableN SMF_WRITE(channel,number,filename$) commandN STEP buried commandN =STR$(number{,len}) string functionN SYSCNTRL(number) system variableN =SYSERR system value/buried commandN =SYSERR${(number)} system valueN =SYSINFO(func) complex system valueN =SYSINFO$(func) system valueN SWAPVAR var1,var2 command print TAB(tabpos{,char$}) buried commandN TCOPY filename$ or #device {TO filename$ or #device} complex commandI {FOR number of lines} {UNTIL match_string$} {LEN number_of_bytes}N TEXT commandN THEN buried commandN =TIME${(value)} system valueN buried commandN TRAP condition link label flow command UNHIDE {RETURN} commandN UNTIL condition_is_true buried command/looping command/2nd part of DO =VAL(string$) math functionN VID$ system value/commandN VID(func) complex system variable WAIT {FOR} value commandN WHILE condition_is_true looping command/1st of WHILEN WORD{area}{(index)} complex system variable XFER direction,protocol,timeout,intvar1,stringvar,intvar2 command optional PRINTN optional TON optional CRN optional CR$N command "breaker"N x + y math/string operandN x - y math operandN x * y math operandN x / y math operandN x == y commandN x += y command aliasN x -= y command aliasN x *= y command aliasN x /= y command alias command delimiterN command delimiterN buried commandN buried commandN buried commandN buried commandN buried commandN text block delimiterN text block delimiterN | (shifted "\") text block delimiterN text block delimiterN text block delimiter-startN text block delimiter-endN x <> y logic operandN x >< y logic operandN x <= y logic operandN x =< y logic operandN x >= y logic operandN x => y logic operandN x = y logic operand/commandN x < y logic operandN x > y logic operand .ALLGLOBAL compiler directiveN .CHAINFILE filename compiler directiveN .DEFMODE parm value compiler directiveN .DEFSTR~name~ = commandstring compiler directiveN .END compiler directiveN .ESCLEAD="char" compiler directiveN .INCLUDEFILE filename compiler directiveN .MINCOMP major.minor compiler directiveN .MINVER major.minor.sub compiler directiveN .PREFIX="pathname" compiler directiveN .SAVEAS "filename" compiler directiveN compiler directiveN remark/compiler directiveN remark/compiler directiveN comment block startN comment block end (for /*)N comment block startN comment block end (for *) )N label compiler directiveN label GLOBAL compiler directiveN ]locallabel compiler directiveN $1to6digit_hexnum compiler directiveN %1to24digit_bit_string compiler directiveN varname{${[index{,length}]}} compiler directiveN _varname{${[index{,length}]}} compiler directiveN &varnum{${[index{,length}]}} local variable/compiler directive Metal.Config Script Command Quick Reference LThe following is a list of each of the Metal.Config's Script Commands, with syntax formats. LNote that when YES is given, ON can also be used, and when NO is given, OFF # can be used (YES=ON, and NO=OFF). MExplanations that end in "[O]" mean that these Script Commands are Optional, * and may not be required for your system. Please refer to "Config Commands" for documentation for each command. script command small explanationN -------------- -----------------N ADDTORESULTMAP= adds "baud" into result [O]N CHARBUFFREQ= sets freq of buffering input [O]N CHATIN=<"string"> sets the text shown when entering chatN CHATOUT=<"string"> sets the text show when exiting chatN CHECKSUM checksums the Metal.OBJ & .OBJ1 files [O]N CIBDIR= where to store the compiled object code [O]N CLEARESULTMAP removes ALL connect return codes [O]N CLOCK= loads in the clock driver for the systemN CREATEDIRS makes Metal creates prefixes 0-9 [O]N CURBLINKRATE= how fast the local cursor blinks & time is updated [O]N CURSOR= re-dfines the local cursor [O]N CURTRACK= turn on/off local cursor tracking [O]N DEFINCPATH= default include path for compiler includes [O]N EXECMODULE= name of code to run before Startup programN FILEENDS ends the ConfigN FILESTARTS starts the ConfigN FREECHAT= defaults to no [O]N LOCALIN=<"string"> sets the text shown when entering local modeN LOCALOUT=<"string"> sets the text shown when exiting local modeN LOCKOBJ= lock object code after compilation [O]N MEMORY= loads in the variable memory driver (VMH)N MODEM= loads in the modem driver for the systemN MODEMAUTO=<"string"> string sent to modem when setting up AutoAnswerN MODEMAXRE= how many times to re-try a modem command (1-8) [O]N MODEMCOMLOCK= check what the modem is getting for commands [O]N MODEMCTSDELAY= delay for flow control [O]N MODEMCTSEOR= 2nd mask for ctsmask [O]N MODEMCTSMASK= bitmask of the modem's Clear To Send flag [O]N MODEMDCDEOR= 2nd mask for dcdmask [O]N MODEMDCDMASK= bitmask of the modem's carrier flag [O]N MODEMDCDTO= resets the timeout value for hi-speed systems [O]N MODEMESC1=<"string"> string sent to modem before other modem stringsN MODEMESC2=<"string"> string sent to modem after esc1N MODEMESCHK= what to do if carrier for esc1 and esc2 [O]N MODEMGENCAR=<"string"> string sent to modem when trying to force carrierN MODEMHANGUP=<"string"> string sent to modem when hanging upN MODEMINIT=<"string"> string sent to the modem when initlizing itN MODEMOFFHOOK=<"string"> string sent to modem when taking it off hookN MODEMPORT= loads in the given modem PORT driverN MODEMPORTLOCK= locks the port at the modembaud [O]N MODEMQUITYPE= suggest BlindN MODEMRESET=<"string"> string sent to modem when exiting MetalN MODEMRINGHAND= normally no [O]N MODEMRINGHELP= normally yes [O]N MODEMSLOT= for SSC.Port driver [O]N MODEMSPEED=<"baud"> defines the baud rate of the modemN NONEGFILES= if yes, bomb with err if filesize >8meg [O]N PAGEBACK= turn off last page to save memory [O]N PATH0= defines where prefix #0 is atN PATH1= defines where prefix #1 is atN PATH2= defines where prefix #2 is atN PATH3= defines where prefix #3 is atN PATH4= defines where prefix #4 is atN PATH5= defines where prefix #5 is atN PATH6= defines where prefix #6 is atN PATH7= defines where prefix #7 is atN PATH8= defines where prefix #8 is atN PATH9= defines where prefix #9 is atN PREFIX= re-defines the default prefix ("*") [O]N PORTCHECKINRATE= re-defines delay between incoming data [O]N PRELOADCIB= load as much of the compiled code as possible [O]N PRINTER= loads in the printer driver for the systemN STARTUP= sets the program to start/restart withN SYSINFO6= sets the default SysInfo(6) value [O]N VIDMAP= defines the default emulation mapper [O] fghijklmnopqrstuvwxyz{|}~ O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== zero or non-zero -- non-zero values are treated as Metal Commands : Section "A" Page ABORT$& Type: system variable/system control ABORT$= keys_to_stop_output_on$ current_keys$ =ABORT$ ABORT$=" " x$=ABORT$ ABORT$=ABORT$+chr$(29) ABORT$="" MABORT$ is used to set or check keys that will cause text output to device #0 M K(local screen and modem) to be stopped - ie: no more text output until the < ABORT$ is cleared or an Input/Get is taken from device #0. LWhen setting ABORT$, you are giving a list of keys, words, that Metal M Kwill stop text output on. Note that lower-case characters are converted to O Mupper-case, so that if you set ABORT$ to, say "a", then hitting either "A" N Lor "a" will cause output to stop. The same goes for setting ABORT$ to "A" - M KMetal doesn't care what the case is of the key, it just checks if it's the M Ksame key. This does not hold true for non-alphabetic keys - thus, if you L Jset Abort$ to the "[" character, hitting "{" (the "lower case" version of "[") will stop output. NReading the current ABORT$ values will result in a string from zero (null) to L J96 characters long - some may be control characters, of course. Be warned E that the keys will be presented in a sorted manner - for example: ABORT$="BA" print ABORT$ The output here will be "AB". The ABORT$ remains active until one of the following has happened: ABORT$ is set to a null value (ABORT$="")) ABORT$ is cleared (CLEAR ABORT$)1 An Input/Get from device #0 is executed. JWhen a key in the ABORT$ is hit during text output, that key is placed in N SYSINFO(2) and SYSINFO$(2), where is stays until you or Metal clears ABORT$. See also: CLEAR, GET, INPUT, PRINT, SYSINFO, TCOPY Type: math function result=ABS( value xp=ABS(yp) NThe ABS - Absolute Value - math function simply returns the positive value of ! the value given. For example: print ABS(1) prints out "1".% print ABS(0) prints out "0".& print ABS(-10) prints out "10". In other words, ABS strips the leading negative from the number. FSee also: ASC, BITVAL, HEXVAL, INSTRING, LEN, MEMAREA, MEMSIZE, PEEK, B @PEEKADDR, PEEKBYTE, PEEKWORD, PADDLE, RANDOM, ROTL, ROTR, SIGN, SYSINFO, VAL ADDR. Type: complex system variable/memory storage ADDR{ area index value or starting_base result or current_base =ADDR{ area index ADDR=memarea(9)+82 ADDR3=memarea(2) print ADDR2 ADDR1(3)=blks lngh=ADDR(20)/word2(7) DADDR - or "Address" - is a very specialized command that is used to * manipulate memory areas in various ways. KADDR "data chunks" are each 24 bits long - if that number sounds familiar, M Kyou're right - it's the exact size of Metal's integers. Thus, ADDR values, L Junlike Byte or Word values, directly reflect the given value, rather than trimming off unused parts. MSince 24 bits is 3 bytes long (24 bits/8 bits per byte = 3 bytes), each ADDR K Iis, naturally, 3 bytes long. They are, by far, the biggest memory eaters D outside of PokeAddr, which also operates on three bytes at a time. HLike Bit, Byte, etc, ADDR may be given one of ten distinct and separate B memory "areas" to work out of. These are the { area } optionals. FThe { area }, if given, is a single digit, ranging from 0 to 9. If no O area } is given, then it defaults into zero. Thus, the following are equal: ADDR=memarea(2)+82 ADDR0=memarea(2)+82 LThe { area must immediately follow the ADDR command word, otherwise you N Lwill cause rather odd things to happen in your code, depending on where you K Imade the mistake - the results could range from a Syntax Error to simply P Nhaving wrong numbers being printed out. There must be spaces between the ADDR and the { area JThe {( index )} optional tells Metal wether or not to set or retrieve the L J"starting base" for that ADDR area, or to set or retrieve a value in that P Narea. This breaks the ADDR command down into two distinct and very separate parts: K(a) If the {( index )} optional is missing, Metal assumes that you wish I Gto manipulate the starting base for the ADDR's area. By setting (ie: H Fequating ADDR{ area } to some value) you are telling Metal where that F DADDR is living at and where to store or look for data at. The value C Agiven will be assumed to be a 16-bit memory address. Likewise, E Creading the ADDR{ area } will retrieve the last set value for that ADDR: ADDR=memarea(2)+82 Sets up where ADDR area 0 (the default, ' %remember?) is going to start at. The 0 ."memarea(2)" value was previously setup using the Allocate command.O print ADDR Displays where ADDR area 0 is currently coming from. E(b) If the {( index given, Metal assumes that you wish to F Dmanipulate the data inside of that ADDR area. Remember, each data F Delement - the "index" - is 3 bytes long. The value of the index may G Erange from 0 - the first element in the ADDR area - to approximately 9,000. ADDR(2)=87 Sets ADDR area 0, element number 2 to the value of 87.N ADDR3(0)=-912 Sets ADDR area 3, element number 0 to the value of 5 3-912 - note that ADDR is the only command of the 2 0Bit/Nibble/Byte etc group that can save off and recall the sign of the data.O print ADDR(9) Displays the value of ADDR area 0, element number 9. IAs previously mentioned, ADDR elements occupy 3 bytes per element. Metal L Jautomatically calculates where the element is at in the starting base for O Mthat area, so you don't need to mess with calculations. ADDR is a very quick O Mand easy "shorthand" way of doing a long POKEADDR/PEEKADDR. For example, the following is equivalent: ADDR use: PEEKADDR/POKEADDR use:6 -------- ----------------------- ADDR0=memarea(2) a0=memarea(2)4 ADDR0(1)=5 POKEADDR((1*3)+a0),54 x=ADDR0(9) x=PEEKADDR((9*3)+a0) LThe nice thing about using ADDR rather than POKE/PEEKADDR is that you don't P Nhave to continuously type in long expressions, and in the case of setting the P Nstarting base ("a0" in our example), you don't have to use a variable. Add to L Jthe fact that using ADDR runs faster than a long POKE/PEEKADDR expression " makes ADDR very powerful indeed! KSee also: ALLOCATE, BIT, BYTE, DEALLOCATE, MEMAREA, MEMSIZE, NIBBLE, PEEK, D BPEEKADDR, PEEKBYTE, PEEKWORD, POKE, POKEADDR, POKEBYTE, POKEWORD, WORD ALLOCATE Type: command/memory control ALLOCATE ( area_num mem_length mem_start ALLOCATE (2,1024) ALLOCATE (9,256,8192) LALLOCATE is used the tell Metal that you want to reserve some portion(s) of N Lthe memory that it uses for "interpreter caching" for your own use. You may O Mreserve from 1 page (256 bytes) to 24k (24756 bytes), and up to 127 "areas", I Gfor your own program's uses - like a for binary run files, data files, workspace areas, etc. MThe area_num operand is a number or expression ranging from 1 to 127. This M Kis basically a "reference" value for your programs to use in order to find ( out where the start of the area is at. MThe mem_length is a value ranging from 1 to 24756, and it is rounded up to O Mthe next even 256 boundary. In other words, if you request 240 bytes, you'll L Jget 256 bytes, and if you request 768 bytes, you get 768 bytes. You don't L have to perform the "rounding up" yourself - the system does that for you. KIf you supply the mem_start , Metal will attempt to use that value as a M location to "steal" memory from. If it finds that it cannot, it WILL NOT LIn order to find out if your request has been carried out - in other words, K Iif enough free, continuous, cache memory is available - you must use the > MEMAREA( area_num ) function, like in the following example: ALLOCATE (7,1024)E if MEMAREA(7)=0 print "Err- Allocate not carried out":return5 print "MemArea7 starts at "MEMAREA(7):return You may, if you wish, re-ALLOCATE an area, like in the following: ALLOCATE (7,1024) ...some code... ALLOCATE (7,2048) JWhat you are doing is telling Metal to "expand" the size of MemArea7 from H F1024 bytes to 2048 bytes. Metal will make every attempt to grant your L Jrequest, but if the cache area is too fragmented, you may find that Metal O Mcouldn't carry it out. In such a case, Metal will give you as much memory as N Lit could , which may be less than you wanted, but will always be as much as you have previously. MNow, how do you get rid of an area once you're done with it? Well, there are three ways: DEALLOCATE ( area_num simply removes it.I ALLOCATE ( area_num setting the mem_length to zero also removes it.I DEALLOCATE(0) this removes of the ALLOCATEd , #*memory areas, and resets the cache buffer back to its original size. MSee also: ADDR, BIT, BLOAD, BSAVE, BYTE, DEALLOCATE, MCLEAR, MCOPY, MEMAREA, C AMEMSIZE, MEMSTRING$, NIBBLE, PEEK, PEEKADDR, PEEKBYTE, PEEKWORD, * POKE, POKEADDR, POKEBYTE, POKEWORD, WORD Type: logic operand result operand1 AND operand2 z=x AND y if hungry AND tired goto sleep EThe AND command word is used to check the preceding ( operand1 ) and A following ( operand2 ) values and return either a 0 or 1 value. GAND will return a 1 value only if both operand1 and operand2 are + non-zero values. Otherwise, it returns 0. AND can be thought of as an logical "multiplier": 0 x 0 = 0 0 x 1 = 0 1 x 0 = 0 1 x 1 = 1 MNote that the actual values of operand1 and operand2 don't really affect J Hthe outcome of the AND command - it just cares if the values are either D zero or non-zero - non-zero values are treated as a "1" value. See also: B.AND, B.EOR, B.OR, EOR, NAND, NEOR, NOR, NOT, OR APPEND Type: command APPEND # device APPEND #1 APPEND #qp MAPPEND is used with a currently open file in one of the File Devices (device N Lnumbers 1 to 4). All it does is simply move the file marker (where the next O Mincoming/outgoing data is going to be put) to the end of the file. APPEND is ' therefor directly equivalent to this: FILEMARK( device )=FILESIZE( device MNote: if you omit the "# device " operand, Metal will use the last specified > ONLINE$, OPEN, POSITION, PREFIX$, PRINT, RENAME, RECNUM, RUN, RUNSUB, TCOPY Type: math function result=ASC( char$ i=ASC("B") first=ASC("Wilson") if ASC(A$)=8 goto left.arrow KASC returns the ascii (American Standard Code for Information Interchange) O Mvalue of the first character of the char$ given. Generally speaking, ASC M Kis used in the if-then example given - to check a character for some known % value, usually a control character. JIf the char$ is null, then ASC will return a value of 0. Otherwise, ASC , will return a value ranging from 1 to 127. FSee also: ABS, BITVAL, HEXVAL, INSTRING, LEN, MEMAREA, MEMSIZE, PEEK, < PEEKADDR, PEEKBYTE, PEEKWORD, PADDLE, RANDOM, SYSINFO, VAL AT or @ Type: buried command print AT( column line print @( column line print AT(0,7) "Hello!" NAT is only used in the Print commands - it is used to re-position the cursor. ! AT works in two possible modes: If the system is in normal ascii text the AutoPos feature is not H turned on, then AT will only affect the local/bbs side of the display. If the system is in a form of terminal emulation that supports G Ere-positioning of the cursor, the AutoPos feature is turned on H F(it normally is), then AT will send out the required control codes to @ the terminal program to re-position the cursor on both ends. KNote that you may freely use the "@" ("at" sign) instead of the AT command word. See also: INPUT, PRINT, VID O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== to the programmer.tion fine with this, as this was don Metal Commands : Section "B" Page B.AND Type: boolean math operand result operand1 B.AND operand2 z=x B.AND y+ if peek($C062) B.AND 128 goto ClosedApple LB.AND is similar to the AND command word, but it does a logical, or "binary = AND" (hence the "B.") instead of a simple test of the data. KWhat this means is that under certain conditions, AND and B.AND will function the same. For example: 1 AND 2 this returns a "1" or "True" value, because both 1 and 2 are not equal to zeroK 1 B.AND 2 this returns a zero - the bits in the "1" and the "2" don't match up.= 3 B.AND 2 this returns a "2" - only that bit matched up. NIn other words, B.AND is a specialized command that is used with given binary data, instead of logical data. KB.AND is generally used to test flags from the Apple's hardware or certain N Lmemory locations that are set up for some other reason. For example, memory K Ilocation $C062 is where Apple has placed a hardware flag for the Apple's O MSolid Apple or "Option" key. By checking bit 7 (which is equal to a value of ( 128), we can tell if it's down or not: if peek($C062) B.AND 128 print "Solid Apple Down" The way B.AND works can be visualized by the following diagram: operand1 bit value 0 1! operand1 ------------------ bit 0 | 0 0 value 1 | 0 1 NIn other words, the result will only be 1 if both values are 1 - otherwise, the result will be zero. HThe B.AND command - bit wise - can be thought of as multiplying the bit values with each other: 0*0 = 0 0*1 = 0 1*0 = 0 1*1 = 1 See also: AND, B.EOR, B.OR, EOR, NAND, NEOR, NOR, NOT, OR B.EOR Type: boolean math operand result operand1 B.EOR operand2 z=x B.EOR y b6i=b6i B.EOR 64 IB.EOR is generally used to reverse or "flip" the values of bits within a P Nnumber. It is of little use, as the EOR and NOT commands are more functional, but it does have its place. KFor example, say we had a variable called "b6i" and we need to reverse the J Hvalues of bits 0 and 8. We can't use the EOR command, as that will just M Kresult in a value of 0 or 1 - we need to have a value greater than one, if possible. Say that "b6i" is currently equal to 85. So we simply do the following: b6i = b6i B.EOR 1+256 ! 1=bit0, 256=bit8 Let's break this down: 85 is equal to the following bit pattern: 85 = %001010101 And 1+256 or 257 is equal to the following bit pattern: 257 = %100000001 So we perform a little digital magic: %001010101 (85) b.eor %100000001 (257) ---------- equal %101010100 (340) MAs you can see, bit 8 - which was zero from the 85 value - has become 1, and 9 bit 0 - which was one in both values - has become zero. The way B.EOR works can be visualized by the following diagram: operand1 bit value 0 1! operand1 ------------------ bit 0 | 0 1 value 1 | 1 0 EIn other words, the result is 1 only if the values of the bits are M different ; If they are both the same value - both 0 or both 1 - then the result will be 0. HThe B.EOR command - bit wise - can be thought of as subtracting the bit > values from each other, and ignoring the sign of the result: 0-0 = 0% 0-1 = 1 (ignore the -, remember?) 1-0 = 1 1-1 = 0 See also: AND, B.AND, B.OR, EOR, NAND, NEOR, NOR, NOT, OR B.OR Type: boolean math operand result operand1 B.OR operand2 bl = cyu B.OR len(a$)( if (mn B.OR tp)=8 then goto crash.ship JB.OR functions similarly to the previous B.And and B.Eor in that it works O Mwith data on the "bit level", but instead of flipping or zeroing bits in the * result, it sort of "adds" them together. IIf either bit in operand1 or operand2 is a 1 value, than that bit in M Kresult will also be 1. The only time the bit in result will be 0 is when / both bits in operand1 or operand2 are zero. The way B.OR works can be visualized by the following diagram: operand1 bit value 0 1! operand1 ------------------ bit 0 | 0 1 value 1 | 1 1 NUnlike the OR command word, which operates on operand values , B.OR operates on operand bits NThe B.OR command - bit wise - can be thought of as adding the bit values with each other: 0+0 = 0 0+1 = 1 1+0 = 1 1+1 = 1 See also: AND, B.AND, B.EOR, EOR, NAND, NEOR, NOR, NOT, OR BIT. Type: complex system variable/memory storage BIT{ area (index) value or starting_base result or current_base =BIT{ area (index) BIT=memarea(9)+82 BIT3=memarea(2) print BIT2 BIT1(3)=true flag=BIT(20) KBIT is a yet another specialized command that is used to manipulate memory areas in various ways. NBIT's "data pieces" are each 1 bit long - thus, they can only hold one of two N Lvalues - a zero or a one. Generally, 1 is considered a "true" value, so for . the most part, BIT is used as control flags. LSince eight bits can fit inside of one single byte, the BIT command is very P Nefficient. By using a small area of memory - usually 32 bytes - you can get a P Nlarge amount of BITs or control flags for your program out of it. In fact, 32 P Nbytes will give you 256 BITs to play with. And the upper limit is 65536 flags # - just 8k of memory. Not bad, eh? HLike Addr, Byte, etc, BIT may be given one of ten distinct and separate A memory "area" to work out of. These are the { area } optionals. FThe { area }, if given, is a single digit, ranging from 0 to 9. If no O area } is given, then it defaults into zero. Thus, the following are equal: BIT=memarea(2)+82 BIT0=memarea(2)+82 KThe { area must immediately follow the BIT command word, otherwise you N Lwill cause rather odd things to happen in your code, depending on where you K Imade the mistake - the results could range from a Syntax Error to simply P Nhaving wrong numbers being printed out. There must be spaces between the BIT and the { area JThe { (index) } optional tells Metal wether or not to set or retrieve the K I"starting base" for that BIT area, or to set or retrieve a value in that O Marea. This breaks the BIT command down into two distinct and very separate parts: If the { (index) } optional is missing, Metal assumes that you wish F Dto manipulate the starting base for the BIT's area. By setting (ie: G Eequating BIT{ area } to some value) you are telling Metal where that E CBIT is living at and where to store or look for data at. The value C Agiven will be assumed to be a 16-bit memory address. Likewise, H reading the BIT{ area } will retrieve the last set value for that BIT: BIT=memarea(2)+82 this example sets up where BIT area 0 (the 0 .default, remember?) is going to start at. The 1 /"memarea(2)" value was previously set up using an Allocate command.J print BIT this example displays where BIT area 0 is currently coming from. If the { (index) given, Metal assumes that you wish to G Emanipulate the data inside of that BIT area. Remember, up to eight I GBITs can reside inside a single byte of memory, so the first eight BIT E Cindexes - numbered "(0)" to "(7)" - start at the first byte of the B "Bit Base", and the next eight BITs are in the second byte, etc. BIT(2)=0 this example sets BIT area 0, element number 2 to the value of 0.M BIT3(0)=1 this example sets BIT area 3, element number 0 to the value of 1.N BIT2(98)=7 this example sets BIT area 2, element number 98 to the value of - see below!O print BIT(9) displays the value of BIT area 0, element number 9, either 0 or 1, nothing else. LWhen you set a BIT (index) value to some number, Metal will set it to zero O only if that operand is zero; otherwise, it will set it to 1 - since it is O Mimpossible to store a number greater than 1 in a BIT, Metal assumes that you + just want to "set the flag", and does so. LSee also: ADDR, ALLOCATE, BYTE, DEALLOCATE, MEMAREA, MEMSIZE, NIBBLE, PEEK, D BPEEKADDR, PEEKBYTE, PEEKWORD, POKE, POKEADDR, POKEBYTE, POKEWORD, WORD BITSTR$ Type: string function result$ =BITSTR$( value flag b$=BITSTR$(access)& print "1990 binary is "BITSTR$(1990) MBITSTR$ (Bit String) is a string function designed to operate in conjunction M Kwith the BITVAL operation. What BITSTR$ does is take the value given and : turns it into a 25-character-long string of 1's and 0's. MThe first character of the string will always be the "%" character - this is L Jwhat Metal uses as a standard "binary string flag" in it's CIB files. The K rest of the string - 24 characters - is the binary equivalent of value HFrom left to right (or the 2nd character to the 25th), the value of the F Dstring is bit 23, then bit 22, bit 21, etc, down to bit 0 (the 25th character). For example, let's say we display the value of the above example: x$=BITSTR$(1990)* x$ will be "%000000000000011111000110" MIf you supply the optional , value, then you are telling BITSTR$ to use P Nsomething other than the default 24 bit display - if you give BITSTR$ a value E of 5 for , then it will use 5 characters plus the "%" lead-in. HIf you want to remove this "%" lead-in, then give it the third optional O M(usually a value of 1). Thus, the following two examples will give something different: x$=BITSTR$(10,5) %01010 (6 characters)8 x$=BITSTR$(10,5,1) 01010 (5 characters) LSee also: CHR$, CNGCASE$, FILEINFO$, HEXSTR$, LEFT$, MID$, REPEAT$, RIGHT$, STR$ BITVAL Type: math function result =BITVAL( bitstring$ access=BITVAL(a$)/ print "the value of the string is "BITVAL(x$) IBITVAL is the converse of BITSTR$, of course. What it does is take a bit L Jstring (of any length, from 0 to 255 characters long) and convert it into N Lit's numerical equivalent. The leading "%" character that BITSTR$ places on M Kits output string is not required - it may be there or not, BITVAL doesn't care. BITVAL will stop converting the string when it: runs out of characters) the character is not "0" or "1". NNote: depending on the size of the string that is converted, the result may or may not be negative. HSee also: ASC, HEXVAL, INSTRING, LEN, MEMAREA, MEMSIZE, PEEK, PEEKADDR, D PEEKBYTE, PEEKWORD, PADDLE, RANDOM, ROTL, ROTR, SIGN, SYSINFO, VAL BLOAD Type: command BLOAD # device memloc length BLOAD # device TO memloc FOR length BLOAD #1,8192,32 BLOAD #3,memarea(1),729 HBLOAD is just what is appears to be - it is a command that reads in raw E Cbinary data from the disk and places it in memory somewhere. BLOAD P N(currently) can only read in data from an open file. A later version of Metal L Jwill have the ability to do a BLOAD from a filename in addition to a file device. JWhen using BLOAD, you must currently have an open file, and you must give J Hwhere you want to load it into ( memloc ) and how many bytes to read in L length ). BLOAD will start reading the file at the current "filemark". LIf the file length or what remains of the file from the current filemark is K Iless than the number of bytes you want to read in ( length ), Metal will M Ksimply zero out the remaining part of memory that would have normally been 9 loaded - Metal assumes that you wish to "blast" memory. For example, you attempt to do the following: BLOAD #1,$300,200 IAnd the file in device #1 is only 100 bytes long. Metal will read in the O Mfirst 100 bytes of the file, and finds that it can't get any more - the file P Nsimply isn't that big. Therefor, the last 100 bytes of memory are zeroed - as E if the file was really 200 bytes long, but the last 100 were blank. NThe alternate syntax is to use the TO and FOR commands in place of the commas P N- BLOAD will function fine with these, as this was done just as a convenience to the programmer. GSee also: APPEND, BSAVE, CREATE, CLOSE, DELETE, DEVICE, DOSERR, FCOPY, F DFILEAUXTYPE, FILEINFO$, FILEMARK, FILESIZE, FILETYPE, FLUSH, INPUT, D BMEMAREA, ONLINE$, OPEN, POSITION, PREFIX$, PRINT, RENAME, RECNUM, RUN, RUNSUB, TCOPY BSAVE Type: command BSAVE # device memloc length BSAVE # device TO memloc FOR length BSAVE #2,memarea(20),128 MBSAVE is the reverse of Bload - it writes binary data out to a file on the O Mdisk. Like Bload, you must give the starting address ( memloc ) and how many bytes to write ( length IBSAVE will write to that device, starting at the current filemark of the K Ifile, and extending the size of the file as needed. When BSAVE ends, the 4 filemark will be where BSAVE stopped writing data. NThe alternate syntax is to use the TO and FOR commands in place of the commas P N- BSAVE will function fine with these, as this was done just as a convenience to the programmer. GSee also: APPEND, BLOAD, CREATE, CLOSE, DELETE, DEVICE, DOSERR, FCOPY, F DFILEAUXTYPE, FILEINFO$, FILEMARK, FILESIZE, FILETYPE, FLUSH, INPUT, D BMEMAREA, ONLINE$, OPEN, POSITION, PREFIX$, PRINT, RENAME, RECNUM, RUN, RUNSUB, TCOPY BYTE. Type: complex system variable/memory storage BYTE{ area (index) value or starting_base result or current_base =BYTE{ area (index) BYTE=memarea(9)+82 BYTE3=memarea(2) print BYTE2 BYTE1(3)=blks lngh=BYTE(20)/word2(7) LBYTE is another specialized command that is used to manipulate memory areas in various ways. NBYTE "data chunks" are each 1 byte long. Unlike Addr, which can store off the G entire value of a variable, BYTE can only handle a range of 0 to 255. HLike Bit, Word, etc, BYTE may be given one of ten distinct and separate A memory "area" to work out of. These are the { area } optionals. FThe { area }, if given, is a single digit, ranging from 0 to 9. If no O area } is given, then it defaults into zero. Thus, the following are equal: BYTE=memarea(2)+82 BYTE0=memarea(2)+82 LThe { area must immediately follow the BYTE command word, otherwise you N Lwill cause rather odd things to happen in your code, depending on where you K Imade the mistake - the results could range from a Syntax Error to simply P Nhaving wrong numbers being printed out. There must be spaces between the BYTE and the { area JThe { (index) } optional tells Metal wether or not to set or retrieve the L J"starting base" for that BYTE area, or to set or retrieve a value in that P Narea. This breaks the BYTE command down into two distinct and very separate parts: If the { (index) } optional is missing, Metal assumes that you wish G Eto manipulate the starting base for the BYTE's area. By setting (ie: H Fequating BYTE{ area } to some value) you are telling Metal where that F DBYTE is living at and where to store or look for data at. The value C Agiven will be assumed to be a 16-bit memory address. Likewise, E Creading the BYTE{ area } will retrieve the last set value for that BYTE: BYTE=memarea(2)+82 this example sets up where BYTE area 0 (the 0 .default, remember?) is going to start at. The 0 ."memarea(2)" value was previously setup using an Allocate command.K print BYTE this example displays where BYTE area 0 is currently coming from. If the { (index) given, Metal assumes that you wish to F Dmanipulate the data inside of that BYTE area. Remember, each data I Gelement - the "index" - is 1 byte long; thus, each index is really the ? "byte number" you want from the start of the Byte Base value. BYTE(2)=87 this example sets BYTE area 0, element number 2 to the value of 87.N BYTE1(4082)=0 this example sets BYTE area 1, element number 4082 to the value of 0.N BYTE3(0)=912 this example sets BYTE area 3, element number 0 to 4 2the value of 912, right? WRONG ! You are setting 6 4this BYTE element to the value of 912 "modulo" (the 5 3remainder) 256 - thus, you are setting this to the % value of 144 (912/256=3 remain 144)M print BYTE(9) displays the value of BYTE area 0, element number & 9. The result will be from 0 to 255. HAs previously mentioned, BYTE elements occupy 1 byte per element. Metal L Jautomatically calculates where the element is at in the starting base for O Mthat area, so you don't need to mess with calculations. BYTE is a very quick O Mand easy "shorthand" way of doing a long POKEBYTE/PEEKBYTE. For example, the following is equivalent: BYTE use: PEEKBYTE/POKEBYTE use:1 -------- ----------------------( BYTE0=memarea(5) b0=memarea(5)+ BYTE0(1)=5 POKEBYTE(1+b0),5+ x=BYTE0(9) x=PEEKBYTE(9+b0) LThe nice thing about using BYTE rather than POKE/PEEKBYTE is that you don't P Nhave to continuously type in long expressions, and in the case of setting the P Nstarting base ("b0" in our example), you don't have to use a variable. Add to L Jthe fact that using BYTE runs faster than a long POKE/PEEKBYTE expression makes BYTE very useful indeed! KSee also: ADDR, ALLOCATE, BIT, DEALLOCATE, MEMAREA, MEMSIZE, NIBBLE, PEEK, D BPEEKADDR, PEEKBYTE, PEEKWORD, POKE, POKEADDR, POKEBYTE, POKEWORD, WORD O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== input CR "Prompt:" a$ CR b$ne 2"le ... Metal Commands : Section "C" Page CALL Type: complex command CALL address options CALL shell$ bitpointer stafflevel CALL memarea(91) CALL xay,name$ CALL "VOLS",bit,staff NThe CALL command is used in two ways: the first is to make an in-line call to N La machine language external that is loaded into some memarea location (CALL 8 cannot be used to run "normal" externals or packages). JThe second way (and the one used the most) is for it to call (run) "shell P Ncommands" - that is, special externals that are stored in 0/COMMANDS that can + be run from the Metal Command Shell line. FUsing the first format assumes that you have a custom-written machine P Nlanguage program loaded into address . The first instruction of this program P Nshould be the opcode "CLD" (clear decimal mode) - Apple uses this for most of H their ProDOS drivers, and it's a simple way of validating the program. KThese "mini-externals" are written the same way as the real ones, they are L Jjust loaded in a different way (you have to do the loading yourself using 8 Bload), and run out of a different location of memory. options , if any, depend on the program being called. JThe "shell" command format requires that you pass it the bitpointer and P stafflevel values. The bitpointer is a 16-bit (2 byte) value pointing the P Nto the user's "bit access flags" record - the shell command check these J to make sure the user has the required access level to use this command. stafflevel is used for some shell commands to make sure that potentially P Nhazardous commands - such as Quit or Term - are only being used by users with O Menough "staff" access. Under FV, staff access levels range from 0 to 3, with P N0 being "normal" users, and 3 being the main system sysop (Metal passes staff P Nlevel 4 - super local sysop - to shell commands when being run from the Shell Command line). See also: BLOAD, EXT, Writing Externals, Shell Commands CHR$ Type: string function char$ =CHR$( number bk$=CHR$(8)" if CHR$(13)=key$ goto hit.return FCHR$ returns a 1-character-long string based on the number given. Not P Nsurprisingly, the character returned is the ascii character for the number Ethus, if 32 is used, a space is returned, and if 65 is used, then an upper-case "A" is returned. GSee also: BITSTR$, CNGCASE$, FILEINFO$, HEXSTR$, LEFT$, MID$, REPEAT$, RIGHT$, STR$ CLEAR Type: complex command CLEAR { extenders CLEAR CLEAR VID CLEAR INPUT NThe CLEAR command is used to reset various and sundry things. Normally, CLEAR M Kis used just to reset the Variable Memory to blank, deleting of your A variables - including those that were PUSHVAR'd onto the stack. KCLEAR may also be followed by a single extender command - using one of the O Mfollowing extenders after a CLEAR will clear your Variable Memory, but # do whatever the explanation says: Extender Does -------- ---- RETURN Clears the Gosub/Return stack.E INPUT Clears the KeyBuff buffer that buffers input from the modem/keyboard.) Clears the For/Next stack.8 ABORT$ This is directly equivalent to ABORT$="".K Using CLEAR VID sends a control-L to both the modem and the B local screens. This is directly equivalent to a PRINT chr$(12);.. This clears the Do/Until stack.4 WHILE This clears the While/EndWhile stack.J This clears the If/LongIf/EndIf stack. Not normally needed.O LONG {IF} Same as CLEAR IF. Either this or CLEAR IF will function exactly the same.1 TRAP Clears of the current TRAPs.O Resets everything - all Hides are lost, all user prefixes are A ?wiped, the screen is reset, everything is as if the system was reset.N array1 to This will erase an array list - the syntax is array(start) array2 array(end) -none- Clears the VMH memory, the Gosub/Return stack, the For/Next B @stack, the Abort$ value, the Do/Until stack, the While/Endwhile B @stack, the If/LongIf/EndIf stack. Does clear the video or the input buffer. See also: POP, TRAP CLOCK' Type: complex system command/variable CLOCK( timer CLOCK( timer option value result =CLOCK( timer option CLOCK(1) CLOCK(2,1)=60*mins sleft=CLOCK(4,2) MThe CLOCK set of commands is used primarily to set, reset, and read the five P Ntimers that Metal has built into it. It also has a little-used extension that P Nallows the program to force an update of the "ticker" in the upper-right hand M Kcorner of the screen (normally this is updated every time the video driver ' handles a carriage return character). GIn order to force the Video Driver to update the "ticker" display, the " command CLOCK(0) should be used: CLOCK(0) JNote that this value cannot be read, as it does nothing more than force a ( normally occurring Metal System Event. KAll five timers are handled in the same fashion and manner as each other - N Lthere is no special syntax for timer number 4 as opposed to timer number 1. ? Simply use the value of 4 instead of 1 for the timer value. JThere are three operations for each timer. The first operation, where the L option is missing, will reset a timer. This is used by simply doing a M KCLOCK( timer ) command, without any options following the timer value. P NThis value cannot be equated to (followed by an equals sign) or read (used in O Man expression). Resetting a clock timer will zero out the time remaining for I Gthe countdown, the time elapsed since the reset to zero, etc. At this L point , the time elapsed counter will begin to increment once each second. KIn order to read how long it was since the clock timer was reset, you must I Guse the CLOCK( timer ,1) syntax. Reading this will return how long, in L Jseconds, it was since the clock timer was reset. This operation cannot be I Gchanged by equating it to a new value, since this would reset the time 7 remaining counter. This is called a "count up" timer. LThe third and final operation is a read and write value, and is used to set J Hor check the time remaining in the counter. This value is reset to zero K I(turned off) when the CLOCK( timer ) command is used. This is called the "count down" timer. NIn order to set the number of seconds to count down from, you must equate the N LCLOCK( timer ,2) to some value. Doing this will set the "count down" value, O Mbut not affect the "time since reset" value. You may currently perform 3 the == (double equals) operation on this command. CLOCK( timer ,2)=3600 (60 minutes count down)F CLOCK( timer ,2)=CLOCK( timer ,2)+60 (add 1 minute to count down) HWhen you read the CLOCK( timer ,2) value, you are reading the number of L Jseconds remaining in this counter since it was equated to a value. Each L Jtime you set the "count down" value to some number, you are resetting the O Mcount down - you are changing when the clock was reset nor how long it was reset. NOnce the count down value reaches zero, it stays there - it doesn't go into a negative number. LThe fifth clock is used only during a INPUT or GET from the keyboard. It is P Nhandled just like the others, but you reference to it by using 5 as the value N Lof timer . Clock #5 is reset each time the system goes looking for a key L Jfrom the user - thus the only usable portion of Clock #5 is the countdown N Lvalue, which should be set to the number of seconds the user has to press a key. KTo trap for a "key timeout", you should use TRAP CLOCK(5) GOTO KEYTIMEOUT. 1 You never have to reset Clock #5 by yourself. INote 1: The CLOCK command is based upon the defined CLOCK= F Dcommand in the Metal.Config script file. If the clock driver is the D BProDOS clock or one that does not support seconds, then the CLOCK H Ffunctions will only return values that are in even multiplies of 60 - D ie: the values will only change once every 60 seconds or 1 minute.N LNote 2: The TRAP CLOCK( timer ) function is based upon the CLOCK( timer ,2) @ >value - if the TRAP function is executed prior to setting the F Dcount-down value, then the TRAP is negated and is not placed in the Trap Table.M KNote 3: If the clock timer(s) "cross days" (ie: go from some time prior to F Dmidnight to some time past midnight), the timers will automatically H Fcorrect themselves and will result in a correct timing value. Thus if E CCLOCK(1) was reset at 23:50:02, and was read next at 00:20:12, the G ECLOCK(1,2) function will return a value of 30 minutes and 10 seconds (or 1810).N LNote 4: All the timers work on and return values based in seconds - thus, F Done minute equals 60 seconds, one hour equals 3600 seconds, and one E Cday equals 86400 seconds. However, since the clocks cannot process G Evalues over one day long (if you are timing something this long, you F Dneed a Cray, not an Apple), the realistic value limit of the clocks is from 0 to 86399.1 Note 5: Adding time to existing time remaining.M The way to do this is as follows: take the time the count-down was D initialized to and then add the extra time to it. Remember, the ? clocks base their counting downs from when they were reset Another way to do this is to take the time remaining, add it to the 7 time spent, and then add the additional time to give. See Also: DATE$, DAYNUM, TIME$, TRAP CLOSE Type: command CLOSE {# file CLOSE CLOSE #2 NCLOSE is the reverse of Open - for each and every Open, you must have a CLOSE 5 in order for ProDOS to update the file on the disk. MIf you don't follow close with a # file value, then CLOSE defaults into the , current Device value that you have set up. KThe value for file may be from 0 to 4, inclusive. If the file value is / zero, then Open'd files are closed off. LIf, on the other hand, you specify a value of 1 to 4, then only that file number is closed off. LIf no file is Open that corresponds to the file value, then the Close has no effect. MCLOSE will generate an error if the given # file value is less than zero or + greater than four ("Device Range Error"). GSee also: APPEND, BLOAD, BSAVE, CREATE, DELETE, DEVICE, DOSERR, FCOPY, F DFILEAUXTYPE, FILEINFO$, FILEMARK, FILESIZE, FILETYPE, FLUSH, INPUT, @ >ONLINE$, OPEN, POSITION, PREFIX$, PRINT, RENAME, RECNUM, RUN, RUNSUB, TCOPY CNGCASE$ Type: string function result$ =CNGCASE$( string$ mode up$=CNGCASE$(name$,0) ias$=CNGCASE$(name$,3) weird$=CNGCASE$(iea$,4) KCNGCASE$ (ChaNGe CASE of string) is a string function that takes the given M string$ value and performs an operation based on mode to it, returning & that modified string into result$ Depending on mode , you perform one of five operations on a string: mode value result example1 ---------- ------ -------C Entire string is "Wilson" becomes "WILSON"$ shifted to upper caseC Entire string is "Wilson" becomes "wilson"$ shifted to lower caseC The first character "WILSON" becomes "Wilson"' of the string is in( upper case, the rest$ is in lower caseI Performs "Name" case "TC WILSON" becomes "Tc Wilson"# shift on stringC Flips the case of "Wilson" becomes "wILSON"" each character KCNGCASE$ is most useful in "prettying up" text prior to being printed. For N Lexample, if you have a data base that consists of names, all in upper case, O Myou could either simply print the upper case names out (like "TC WILSON" and K "BILL ROBERTS"), or perform a CNGCASE$, like the following example shows: open #1,"names" loop input #1,a$ if a$="" goto end.loop3 print CNGCASE$(a$,3) ! do "name" conversion goto loop end.loop close #1 return JSince you would have to print out the value of a$ in order to display the O Mnames, you can use the CNGCASE$ function to pre-process a$ and print out "Tc Wilson" and "Bill Roberts". LNote that prior case of the characters of the string are taken into H account when CNGCASE$ operates - it shifts the case to what is needed. Special note on mode 3 (name shift): IMode 3 shifts the entire string to lower case and then scans through it, O Mlooking for certain characters - these characters are: the space, a dash, or O Ma double-quote mark. Once one of these are found, the character following it P N(provided it is an alphabetic character) is shifted to upper case. This means the following will happen: arc-angel becomes Arc-Angel. arc angel becomes Arc Angel- arcangel becomes Arcangel0 "arc" angel becomes "Arc" Angel KSee also: BITSTR$, CHR$, FILEINFO$, HEXSTR$, LEFT$, MID$, REPEAT$, RIGHT$, STR$ COMPILE Type: command COMPILE filename$ {MODE( function COMPILE a$ COMPILE "1/main" MODE(1) GThe COMPILE command is used to force Metal to compile a module without M Kactually running it. All the normal compile "error reports" are displayed, H Fbut the system does run the compiled module - it returns to the , original module, much like a Gosub/Return. LThe filename$ parameter is, of course, the file to compile. If the source L file does not exist, the COMPILE command will crash with a system error. LNormally, COMPILE is used to pre-compile a possibly changed module. In this K Iregard, COMPILE acts just like the normal Run command - it checks if the K Isource file has been changed, the object code file is missing, or if the J Hobject code file is bad. If any of these conditions exist, COMPILE will ) automatically "pre-compile" the module. IIf you follow the COMPILE filename$ with the optional MODE( function Nparameter, where function is any non-zero value (in other words, MODE(1) ), N Lthen COMPILE will force the system to re-compile the module, no matter if the thing needs to or not. HA good example of using the COMPILE command can be found in viewing the M PRECOMPILE.S source file, which batch-compiles the entire BBS upon startup. See also: RUN, RUNSUB CR or \ Type: buried command print CR{ (repeat) input CR .... variable CR variable ... print CR(2) "Line 1" CR "Line 2" input CR "Prompt:" a$ CR b$ NCR (Carriage Return) is a buried command - it is never executed by Metal, but K Ithe Print and Input commands both allow the CR command to be used within them. LWhen using CR in a Print statement, CR will output a control-M character at M Kleast one time, or for as many as the optional repeat value has. This is O Museful when displaying lines of text without having to resort to extra Print commands. JWhen using CR in an Input statement, CR may be used prior to the prompt P Nstring to print a return out. If so, unlike the Print, Input will allow $ you use the optional repeat value. MGenerally, CR is used as a separator in Input statements where more than one L Jvariable value is being gathered - in this function, CR works as a "place G holder", telling Metal to look for a control-M between the variables. See also: INPUT, PRINT CR$ or \$ Type: string function print CR$ a$=CR$ if i$=CR$ goto exit LThe CR$ command will simply return a 1-character string that is nothing but N Lthe carriage return character (ascii code 13, or chr$(13)). The only reason N Lfor this command is to allow the BBS program to run slightly faster, and to make your programs smaller. See also: DATE$, ESC$, FILE$, SYSINFO$, TIME$, CREATE Type: command CREATE filename$ filetype auxtype CREATE subdir$ CREATE text$,4 CREATE dhr$,6,8192 LCREATE is the command you must use in order to make a new file on the disk. P NOnce this file is created, you may begin to write to it and fill it with data P N- reading from a newly created file will result in no data being gather (none was stored off). LBy default, CREATE creates "sub-directory" files on the disk. Sub-Dir files H Fare very useful for storing data files away from the main directory - N Lconsidering that ProDOS only allows 51 files on the main directory, this is not a bad idea at all! IIf you give CREATE the optional filetype , you are telling Metal not to L Jcreate a sub-directory file, but to create a new file of some other type. O MGenerally, you will most likely be using one of the following three filetype values: filetype means -------- -----, "Typeless" ("NON") file.> "Text" ("TXT") file - what you're reading.D "Binary" ("BIN") file - pictures, routines, etc. EAfter you give the optional filetype, you may also give the optional J auxtype , which your program can then later access or Metal can use to I Gperform various things. If you don't give this value, Metal will use a default value of zero. LThe auxtype ("Auxiliary Filetype") is not used by ProDOS per say, but it is K Iused by some programs to get additional information about a file without 3 having to actually open and read it. For example: TXT (Text) files: the auxtype is the size of each random access record, in : 8bytes or characters. If this value is zero or one, then 1 /the file is consider sequential (ie: a text or documentation file). BIN (Binary) files: Basic.System defines the auxtype of a binary file as 2 0the "default load address". For example, hi-res 6 pictures generally have an auxtype of 8192 or 16384. LMetal makes little use of auxtype value, with the exception of the POSITION J Hand RECNUM values, which use the value as the size of the random access A record (remember this fact, it's important in the "R" section). MMetal will not use the auxtype value when creating new sub-directory files - 9 it always uses a value of zero, as per Apple Standards. KWhen attempting to create a file, Metal will check and see if the pathname K Igiven actually exists - if not, Metal will attempt to create the missing O Msub-dirs in the pathname, making it legal. For example, say you have a newly J Hformatted disk called "/BLANK", and wish to create a binary file called O M"/BLANK/DIR1/DIR2/BINFILE" - Metal, since it cannot find the DIR1 directory, P Ncreates it; it then has to create the DIR2 directory, and finally the BINFILE O Mfile. This operation is totally automatic, and you never have to worry about doing this yourself. MNote: Metal does format disks with the CREATE command - if you need to ? =make a blank disk or erase an existing one, you must use a filing/disk utility program. FSee also: APPEND, BLOAD, BSAVE, CLOSE, DELETE, DEVICE, DOSERR, FCOPY, F DFILEAUXTYPE, FILEINFO$, FILEMARK, FILESIZE, FILETYPE, FLUSH, INPUT, @ >ONLINE$, OPEN, POSITION, PREFIX$, PRINT, RENAME, RECNUM, RUN, RUNSUB, TCOPY O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== Metal Commands : Section "A" Metal Commands : Section "D" Page DATE$ Type: system value result$ =DATE$ td$=DATE$ print "Today's date: "DATE$ LThe DATE$ command simply returns the current date from the installed ProDOS J Hclock, in the standard mm/dd/yy (Month/Day/Year) format. If no clock is E Cinstalled in ProDOS, then DATE$ will return a string consisting of "00/00/00". The returned string is always eight (8) characters long. See also: CLOCK, DAYNUM, TIME$ DAYNUM Type: system value result =DAYNUM{( date$ flag d=DAYNUM day$=days$(DAYNUM) day=DAYNUM(t$)2 print "Today is the "DAYNUM"th day of the week."9 print "Today is the "DAYNUM(Date$)"th day of the week.": print "Today is the "DAYNUM(Date$,1)"th day since 1900." HDAYNUM is used to return the "day number", based on the installed Clock N LDriver (not the ProDOS clock driver, but the Metal clock driver, setup from N Lthe Metal.Config file). The result is always within the 0 to 7 range. The O following is a list of the eight possible result values and what they mean: result means ------ -----. unable to figure out day number SUNDAY MONDAY TUESDAY WENSDAY THURSDAY FRIDAY SATURDAY GYou are probably wondering "Well, why don't you just return the string M Kinstead of a number?". The answer is simple: your BBS program can handle a M number instead of a word much easier, plus you can change the what the H Ftext output can be quickly, instead of going through a lot of If-Then 9 statements - just use an array, like the above example. NIf you use the optional ( date$ ) parameter with DAYNUM, Metal will calculate O Mthe current day of the week based upon the date$ given. This string can be P date in history, from January 1st, 1900 to December 31st, 1999. You can O Muse this instead of the normal DAYNUM function to figure out the current day O Mof the week by passing the DATE$ system value to DAYNUM, as the second Print L Jexample shows (Both of the first two Print examples will return the exact same value). NGiving DAYNUM the optional flag set to 1 will cause DAYNUM to calculate the O Mgiven date$ value and return a number ranging from 1 to 36524. This number O Mis the number of days since January 1st, 1900. Thus "01/01/00" will return 1 P N(the first day), and "12/31/99" will return 36524 (the last day). DAYNUM will = take care of the leap years and correctly adjust the value. NUsing DAYNUM in this manner is handy to write routines to figure how long ago something was. For example: lcd$=last_call_date$ x=DAYNUM(Date$,1)-DAYNUM(lcd$,1)* print "You were last on "x" days ago." See also: CLOCK, DATE$, TIME$ DEALLOCATE Type: command DEALLOCATE( area_num DEALLOCATE(5) DEALLOCATE(0) NDEALLOCATE is used in conjunction with the Allocate command, so naturally, it K Iaffects the Cib Cache Buffer. What DEALLOCATE does is free up the memory P Npages marked with Allocate so that the Cib Cache Buffer has more room to work with. The area_num passed can be one of three types: A value of 0: this removes Allocated pages from use, and 3 1resets the Cib Cache Buffer to it's original 24k size.E A value of 1 to 127: this just removes that single memory area 4 2Allocated, leaving any others still in use. If no / -such area was Allocated, then nothing really happens. KSee also: ALLOCATE, ADDR, BIT, BLOAD, BSAVE, BYTE, MCLEAR, MCOPY, MEMAREA, C AMEMSIZE, MEMSTRING$, NIBBLE, PEEK, PEEKADDR, PEEKBYTE, PEEKWORD, * POKE, POKEADDR, POKEBYTE, POKEWORD, WORD DELETE Type: command DELETE filename$ DELETE "/hard1/basic.system" DELETE a$ GDELETE, quite simply, removes the passed filename$ from the disk. It @ operates just the same like the Basic.System command "Delete". DELETE will not do the following: (a) Delete a "locked" file.- (b) Delete a file that is currently open.D (c) Delete a sub-directory that has one or more files within it. (d) Delete all the files within a sub-directory (at least, not at this H point in time, but this will be an option with future a Metal version) LNote: Metal does delete or "erase" disks using the DELETE command. If I Gyou need to format a blank disk or erase an existing one, you must use a filing/disk utility program. JSee also: CREATE, CLOSE, DOSERR, FCOPY, FILEAUXTYPE, FILEINFO$, FILESIZE, > FILETYPE, ONLINE$, OPEN, PREFIX$, RENAME, RUN, RUNSUB, TCOPY DEVICE Type: system variable result =DEVICE DEVICE= new_device pushvar DEVICE DEVICE=6 NDEVICE is used to reset the default input/output (i/o) device. Normally, this L J"default device" is set to zero - which is the local video along with the L Jmodem. However, there are times when re-setting the default device can be useful. NFor example, if you set the DEVICE equal to "6", which is the printer (and is O Moutput only, by the way), then any further Print's that don't explicitly say B "print to this device" will go to device number 6 - the printer: print "This is to the screen (device #0)" DEVICE=68 print "And this is on the printer! (device #6)"B print #0,"Hey, back the screen, but by choice this time!" MDEVICE also works with the Input command, and is generally used with devices J H1 through 4 (the file channels). The following two Input's are directly equivalent: open #1,"file" DEVICE=1 input a$ input #1,b$ close #1 Both A$ and B$ will be taken from device #1, the open file. Note that DEVICE will stay at whatever you set it until: (a) the system is rebooted. (b) the system resets, either by a program error and a auto or manual estart.N (c) you press control-Reset to get into the Reset prompt line and then do a estart. DEVICE is not affected by a Clear. LIt is always a good idea to reset the DEVICE to zero after you are finished P Nwith it. If you wish, you may use the following programming lines to save and restore the default device: pushvar DEVICE ...your code... pullvar wxyz DEVICE=wxyz Note that you cannot (currently) do a PullVar using the DEVICE command word. FSee also: APPEND, BLOAD, BSAVE, CLOSE, CREATE, DELETE, DOSERR, FCOPY, F DFILEAUXTYPE, FILEINFO$, FILEMARK, FILESIZE, FILETYPE, FLUSH, INPUT, @ >ONLINE$, OPEN, POSITION, PREFIX$, PRINT, RENAME, RECNUM, RUN, RUNSUB, TCOPY Type: looping command ...command(s)... UNTIL condition_is_true print "Hit a key!"; get i$ UNTIL i$="E" print "Exited!" MThe DO command is one of Metal's special "looping commands" - the others are FOR-NEXT and WHILE-ENDWHILE. LDO-UNTIL will continue to loop until the set condition becomes a non-zero N L(true) value. Basically, using the DO-UNTIL loop is equal to a IF-THEN-GOTO M Ksetup, but without the labels. So, the following two examples will perform exactly the same: a=03 labelG print "A is equal to ";a print "A is equal to ";a4 a==+1 a==+1B UNTIL A=20 if a<>20 goto label JSo each version of the loop will run until A reaches the value of 20. The J reason for using a DO instead of an If-Then-Goto is that the DO command: (a) runs faster than an If-Then (b) doesn't require a label. KHowever, there are times when using a DO-UNTIL is not applicable - Exiting P Nfrom the middle of a DO-UNTIL is a bit difficult (you have to use a POP DO to M Kget out of it prior to a GOTO), and you may only have up to eight DO-UNTIL N loops running at any given time (ie: you may only nest the DO 8 levels deep) KNote that the DO-UNTIL loop will execute at least once , no matter if the ; condition value is true prior to the start of the loop. LSee also: CLEAR, ELSE, END, IF, LONG IF, FOR, GOTO, GOSUB, NEXT, POP, STEP, THEN, UNTIL, WHILE DOSERR Type: system value result =DOSERR print "The last ProDOS error was: "DOSERR2 open #1,f$:x=DOSERR:close #1:if x goto FileError JDOSERR is simply a command that does a peek of memory location $BF0F (the O Mlast ProDOS error number). The value of DOSERR changes each and every time N La DOS command is used (such as Open, Close, Create, or Filesize). Thus, the M Ksecond example above had to save off the possible DOSERR reported when the . file was opened, since Close will change it. Error Text Number (Hex) Number (Dec)D -------------------------------------- ------------- -------------8 No Error $00 08 Invalid MLI Function $01 18 Invalid Parameter Count $04 49 Interrupt Table Full $25 379 I/O Error on Disk Media $27 399 No Device Connected to Slot/Drive $28 409 Disk is Write Protected $2B 439 Volume(s) have been Switched $2E 469 Device is Offline $2F 479 Invalid Pathname Syntax (Bad Pathname) $40 649 Too Many Files Open at Once $42 669 Invalid Reference Number $43 679 Nonexistent Path in Pathname $44 689 Volume not Online $45 699 File Not Found in Pathname $46 709 Duplicate Filename (RENAME Error) $47 719 Disk Media is Full $48 729 Volume Master Directory Full $49 739 Incompatible ProDOS Version $4A 749 Unsupported File Storage Type $4B 759 End Of File $4C 769 Position past End Of File $4D 779 Access Error (File is Locked) $4E 789 File Already Open $50 809 File Count Bad in Directory $51 819 Not a ProDOS Disk $52 829 Bad Parameter $53 839 Volume Count Buffer Overflow $55 859 Bad Buffer Address $56 869 Duplicate Volume Online $57 879 Bad Volume BitMap $58 88 FSee also: APPEND, BLOAD, BSAVE, CREATE, CLOSE, DELETE, DEVICE, FCOPY, F DFILEAUXTYPE, FILEINFO$, FILEMARK, FILESIZE, FILETYPE, FLUSH, INPUT, @ >ONLINE$, OPEN, POSITION, PREFIX$, PRINT, RENAME, RECNUM, RUN, RUNSUB, TCOPY O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== EDIT(14) reserved.tion "A" Metal Commands : Section "E" Page EDIT' Type: complex command/system variable EDIT( index value result =EDIT( index EDIT(1)=1 lines=EDIT(2) EThe EDIT command is used to access and control the built-in Line and K IFullScreen editors (packages 01 and 02, respectively). You access either editor by the EDIT(1) command: EDIT(1)=1 execute the Line EditorG EDIT(1)=2 execute the FullScreen Editor (currently only PTSE) You may check what version was accessed last by the following: last =EDIT(1) returns 1 for Line, 2 for FullScreen, 0 for neither And you may re-execute the last Editor type by doing: EDIT(1) without the "=x" expression. MThe EDIT(2) command is the number of lines that were in the editor's buffer. P NThis is a read only value. Normally, you check this when one of the Editors - exits to check how many lines were entered. lines_entered =EDIT(2) returns the number of lines entered in the ' buffer, from 0 (empty) to 65000 (max) NThe EDIT(3) command is also a read only value - it returns the "error code" back from the editor: editor_err =EDIT(3) 0=no errors, file was saved correctly.B 1=user aborted edit, nothing saved off.? 2=attempt to save empty buffer file.M 3=file was not saved to disk - Edit$(3) value was not set up or was null.K 4=file was not saved to disk correctly - ProDOS 6 4error of some sort. The file may exist partially on 6 4the disk, or may not. Check the DosErr system value for the error code.2 5-255: future expansion JBoth editors have various options that control the default justification, L Jword wrapping (splitting of the text at the edge of the screen), the line P Nnumber prompting, the "Hot Dot" feature, and the output file control. The are 1 setup through the EDIT(4) to EDIT(16) commands. KWhen the Editor executes, it uses whatever values are currently present in P NEDIT(4) through EDIT(7). When the Editor exits (either by Abort or Save), the J Hcurrent values are reflected - thus if the user changes from Hot Dot to ) normal, then EDIT(5) will be changed EDIT(4) current justify mode. 0=none,1=left,2=right,3=center.: (Line Editor only, not currently used in FSED)- EDIT(5) current hot dot mode. 0=off,1=on.: (Line Editor only, not currently used in FSED)1 EDIT(6) current word break mode. 0=off, 1=on.0 EDIT(7) current prompting mode. 0=off, 1=on.: (Line Editor only, not currently used in FSED) KWhen the Editor saves the file, it saves it to EDIT$(3) filename (if set). N You can change how the Editor saves this "outfile" with the EDIT(8) command: EDIT(8) outfile control.A 0=create w/error, will error if EDIT$(3) file exists.A 1=save normal, will overwrite existing EDIT$(3) file.? 2=append to existing EDIT$(3) (if said file exists) MSpecial options exist for each editor, which is controlled by the EDIT(9) to N LEDIT(16) flags. For most usage, these should be set to zero; for users with M Kstaff access, these should be set to 1. When the Editor's exit, these will always be reset to zero. EDIT(9) If this is one, allows the usage of the Include/Load % From/Attach options in the Editors.M EDIT(10) If this is one, allows the use of the Save As... option. This C Alets the user save the file as whatever he wants and to continue editing.O EDIT(11) If this is one, the user has access to the Clipboard functions. A In order for this to work, EDIT$(4) must be set up (see EDIT$).M EDIT(12) If this is one, then the FullScreen Editor will allow the use - of Inverse text; otherwise, it prevents it.M EDIT(13) If this is one, then the FullScreen Editor will allow the use C Aof MouseText (ProTerm Special Emulation); otherwise, it prevents EDIT(14) reserved. EDIT(15) reserved. EDIT(16) reserved. GBy now, you're wondering "How can I check for the number of characters N Lentered?". Very simple. Since you explicitly give the Editors a pathname to P Nsave the text to when they exit (actually, when the user says "Save it"), you O can perform a FileSize(Edit$(3)) to return the size of the file. For example: ln=filesize(edit$(3))0 print "You entered "ln" characters." LThe Editors use Variable Memory as a storage space for the text - these are N Lstored as special variables that your CIB files cannot access. Each line is O Mfrom 0 to 79 characters long, and there may be from 0 to 65,000 lines stored in memory. IRoughly, each line takes from 10 to 90 bytes of variable memory - during H Fnormal editing, this averages out to 80 characters over the long run. P NAssuming that the maximum number of lines a user uses is 256, this translates P Ninto around 20k of variable memory - 18,000 characters (subtracting overhead) @ of posting. This fits nicely into a 30k variable memory setup. JThis "internal buffer" is automatically erased when the Editor exits, and N your Free value will read approximately the same as when the Editor started. See also: EDIT$, EXT, FCOPY, TCOPY EDIT$ Type: system variable result$ =EDIT$( value EDIT$( value string$ curtab$=EDIT$(1) EDIT$(3)=filetosave$ IThe EDIT$( value ) command is used to control some parts of the Editors. M KThese controls range from the default tab line, what file, if any, to load E into the Editor, and what file, if any, to save the editor text to. MNote: the EDIT$ is not really a command, it is just a normal variable that N LMetal has been programmed to handle specially. You can use EDIT$, EDIT$(0), L JEDIT$(20), EDIT$(5,6), etc - Metal just uses EDIT$(1) to EDIT$(4) for the Editor's uses. MBoth Editors use a TabLine - the FSED shows its Tab Line all the time, while P Nthe Line Editor only shows it when requested. This tab line defaults to a set H Fvalue, but it is always returned and may be set when the Editor's are executed: lastabline$ =EDIT$(1) returns the last tab line used. If this is 2 0null or not equal to a string 79 chars long, it was never set.K EDIT$(1)= newtabline$ sets the tab line to be used next time. If 1 /this is not a string that is 79 chars ling, it / -will be used, and the default tab line will be used. HYou may want to load a file or start fresh with a blank editor. This is ! handled via the EDIT$(2) value: cursource$ =EDIT$(2) returns the current filename of the file to 2 0load. This file is "broken" into lines that are 1 /79 characters long, and all control characters + )are either stripped out (Line Editor) or converted (Full Screen).L EDIT$(2)= filename$ sets the filename of the file to load. Same . ,formatting rules as above. If this is null, 1 /then the editor will NOT load in any file, and + instead, start fresh with a blank editor. KIn order to tell the Editors where to save the file - if at all - you must N Lset the EDIT$(3) up. This is the pathname of the target TXT file. If this O Mstring is null, then the file is not saved at all , and any text typed will ? be saved off, and will be lost when the Editor exits. curfilename$ =EDIT$(3) returns the current filename of the file to save to.M EDIT$(3)= filename$ sets the filename of the file to save to. If 1 /null, then the file is not stored to disk, and 2 0any entered text will be lost. How this file is , saved is determined by the EDIT(8) option. FBy setting EDIT(11) to 1, you allow the Editor's to use the Clipboard P Nfunctions. These require that EDIT$(4) be set up. This is the filename of the L JClipboard file. If this string is null, then the Editors will not use the Clipboard function. curfilename$ =EDIT$(4) returns the current filename of the Clipboard file.O EDIT$(4)= filename$ sets the filename of the Clipboard file to use . ,when the Editors are "clipping" part of the % #text out for later use. A value of 2 0"$/CLIPBOARD" is suggested. This Clipboard file 2 0is cleared or deleted from Editor session to Editor session. See also: EDIT, EXT, FCOPY, TCOPY ELSE Type: buried command H{long} if math function then do if true commands :ELSE do if false commands if a=0 then print "Zero":ELSE print "Not Zero" long if m mod 4=3 print "From 0 to 2" ELSE print "It's Three" end if HThe ELSE command is used in conjunction with the If/LongIf/Then command O Mstructure. For a complete treatment on the ELSE command, you should refer to " the If and Long If explanations. See also: CLEAR, END, IF, LONG IF, POP, THEN Type: complex command END { extender END IF END WHILE IThe END command is used to close off a LongIf statement or a While loop. L JUsing END without either an IF or WHILE extender , the END command tells O MMetal to stop running the CIB program, and it crashes the system with an End ' of Program Error (SysErr number 255). So there are three possible extender s for the END command: extender does -------- ----1 Terminates a LongIf statement< WHILE Signals the end of a While/EndWhile loop= -none- Crashes program with End of Program Error END can generate one of three possible errors: LEnd of Program Error (SysErr number 255): neither an IF or WHILE command followed the END command.P NEnd If without Long If (SysErr number 183): There is not a Long If statement currently running.I GEnd While without While (SysErr number 185): There is not a While loop currently running. See also: CLEAR, ELSE, IF, LONG IF, POP, THEN, WHILE Type: logic operand result operand1 EOR operand2 z=x EOR y3 if youdead EOR hedead print "One of you is dead!" EThe EOR command word is used to check the preceding ( operand1 ) and A following ( operand2 ) values and return either a 0 or 1 value. LEOR stands for Exclusive-OR, and it returns a value of 0 if both operand1 Kand operand2 are the same logical value (both zero or both non-zero). If O Mthe values of operand1 and operand2 differ, then EOR will return a value of 1. EOR can be thought of as an logical "subtracter": 0 - 0 = 0$ 0 - 1 = 1 (sign is dropped) 1 - 0 = 1 1 - 1 = 0 MNote that the actual values of operand1 and operand2 don't really affect J Hthe outcome of the EOR command - it just cares if the values are either D zero or non-zero - non-zero values are treated as a "1" value. See also: AND, B.AND, B.EOR, B.OR, NAND, NEOR, NOR, NOT, OR ESC$ Type: string function if i$=ESC$ goto a$=ESC$ print ESC$ LThe ESC$ command simply returns back a single character consisting of ascii P Ncode 27 (the escape character). It is normally used to check single-character K Iinput from the user to see if he/she has pressed the ESCape key (usually + aborting whatever function is occurring). See also: CR$, GET, INPUT Type: complex command EXT filename$ or # package number {, optionals EXT "7/exploder" EXT #200! EXT #128,0,80,2,15,"GF","Files" FThe EXT command is used to load in an run machine language programs - N Lgenerally, it is used to run custom "packages" that you have placed in your D "0/" directory, but you can just as easily run a literal filename. NDepending on what the external is supposed to do, and what (if any) following J optionals (or arguments) are there, the external may just print out a L Jstring, draw a PTSE window, transfer some files, view a hires picture, or even format your disk. NFor more information on how to use a particular external, you should refer to % the documentation on that external. GFor information on writing externals, you should refer to the document M K"WRITING.EXTRNLS", which covers the Metal machine language environment and the "package" format. See also: XFER, document WINDOWING.EXTNL, document WRITING.EXTRNLS !"#$%&'()*+,-./0123456789:;<= O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== FILETYPE, FILESIZE, OPEN, RUN, RUNSUB, TCOPY, XFERFILE Metal Commands : Section "F" Page FCOPY Type: command KFCOPY sourcefile$ or # sourcedevice TO targetfile$ or # targetdevice {MODE( option )} {LEN( length FCOPY f$ to #3 FCOPY a7$ TO "/ram5" MODE(4)' FCOPY #1 TO "7/FILE" MODE(0) LEN(800) LFCOPY (File COPY) is like Tcopy, but instead of dealing with text, it deals O Mwith anything - it's also much faster, since it copies the file in 8k chunks L Jinstead of 1 byte at a time like Tcopy. Also note that Tcopy doesn't like O Mhandling non-text data (using Tcopy to copy your ProDOS file would result in a mess). sourcefile$ is the file to copy - it is a complete filename. If there is no N Lpath in the filename, then the current prefix value is used. Note that this K Ifile must be a non-DIR file, so using "/RAM5" or something similar for , sourcefile$ will result in a major mess. NYou may optional use # sourcedevice instead of sourcefile$ - in this case, L Jsource data is taken from the currently open sourcedevice . Data is read 1 starting at the current filemark into the file. targetfile$ is either the target filename or the target directory - this # depends on the value of option FAgain, you may use # targetdevice instead of targetfile$ - in this A ?instance, the target data is written out to the currently open L targetdevice . Data is written starting at the current filemark into the file. IFCOPY uses a default mode option of 0. If you supply a Mode( option ), P NFCOPY will use the option value as a bit-pattern; this means FCOPY can have % multiple options at any given time: bit 0: if this is 1, then the data in sourcefile$ is appended to targetfile$ bit 1: if this is 1, then after the copy, sourcefile$ is deleted. Not 6 used nor checked when using # sourcedevice is used.O bit 2: if this is 1, then targetfile$ is sub-directory, and the filename F Dportion of sourcefile$ is pulled off and used as the filename for D targetfile$ . Not used nor checked when using # targetdevice is used.O bit 7: if this is 1, and the length value (either given or used from the F Dsize of the file to be copied) is over 32k, then FCOPY will display D Ba "percentage done" report as it copies the file. This is nice to E Cuse, since it lets you (or your users) see how far along the FCOPY F Dis and gives them a feel that the system is doing something and not G Eignoring them. Using or not using this optional flag has effect , on how the copy is done or how fast it is. bits number does... ---- ------ -------< %000 normal copy, over-writes targetfile$ %001 appends data to end of targetfile$ %010 deletes sourcefile$ when copy is doneJ %011 appends data to targetfile$ , deletes sourcefile$ %100 same as 0, but targetfile$ is a sub-directoryE %101 same as 1, but targetfile$ is a sub-directoryE %110 same as 2, but targetfile$ is a sub-directoryE %111 same as 3, but targetfile$ is a sub-directory KNormally, FCOPY copies the entire file (or what is left of it to be read G Eafter it is opened), but you can override this by using the optional O MLEN( length ) parameter. Using this will force FCOPY to copy length number N Lof bytes. Note that this value be larger than the size of the file to J Hbe copied, in which case FCOPY will just use zeros to fill out what was K Imissing. Note that FCOPY also does this when you have it copy a "sparse" file. IHere are eight examples to fully explain what FCOPY does for each of the options FCOPY "/hd1/prodos" TO "/new.disk/prodos.copy" MODE(0) In this example, both the source and target pathnames are complete - each H Fone holds a filename (source is the file "prodos", target is the file M K"prodos.copy"). The file "prodos.copy" will be overwritten (if it exists), 1 and the original file is intact after the copy. FCOPY "/hd1/prodos" TO "/new.disk/prodos.copy" MODE(1) This example is the same as the one using MODE(0), but the data from the L Jsource ("/hd1/prodos") will be appended to the target file. If the target G Efile doesn't exist, then this FCOPY example functions the same as if MODE(0) was used. FCOPY "/hd1/prodos" TO "/new.disk/prodos.copy" MODE(2) Again, this functions the same as the MODE(0) example, but after the 8 copy, the source file ("/hd1/prodos") will be deleted. FCOPY "/hd1/prodos" TO "/new.disk/prodos.copy" MODE(3) This combines both MODE(1) and MODE(2) - the data from the source file L J("/hd1/prodos") is appended to the target file ("/new.disk/prodos.copy"), 1 and after the copy, the source file is deleted. FCOPY "/hd1/prodos" TO "/new.disk" MODE(4) In this example, FCOPY is being told to pull the file - "prodos" from the H Fsource filename and use it as the target file - thus, the real target M Kfilename is "/new.disk/prodos". If the target file exists, then it will be overwritten. FCOPY "/hd1/prodos" TO "/new.disk" MODE(5) This functions the same as MODE(4), but if the file "prodos" already L Jexists on the "/new.disk" volume, then the data from the source file will be appended to it. FCOPY "/hd1/prodos" TO "/new.disk" MODE(6) Again, same as MODE(4), but after the copy, the "/hd1/prodos" file will be deleted. FCOPY "/hd1/prodos" TO "/new.disk" MODE(7) Combines MODE(4), MODE(5), and MODE(6) together in one. NFCOPY copies everything about the file - the filetype, the auxtype, and the L Jaccess bits. Thus, if the source file is a locked, invisible system file, I then the target file will also be locked, invisible, and a system file. KNote: at the time of this writing, FCOPY doesn't handle ProDOS errors very ? well, nor will it copy entire directories/entire directories.P NNote: If FCOPY cannot find 8k of free variable memory for the copy buffer, it J Hwill instead use a 256-byte buffer. This means that FCOPY will function ! slower, but it will still work. LSee also: APPEND, BLOAD, BSAVE, CREATE, CLOSE, DELETE, DOSERR, FILEAUXTYPE, C AFILEINFO$, FILEMARK, FILESIZE, FILETYPE, ONLINE$, OPEN, PREFIX$, RENAME, TCOPY FILEACCESS Type: system variable result =FILEACCESS( filename$ or file device FILEACCESS( filename$ or file device value a=FILEACCESS("/hd1/prodos")$ if FILEACCESS(2)=1 goto FileLocked FILEACCESS(f$)=$C3 FILEACCESS(1)== b.or 4 IThe FILEACCESS command is used to read or change the "access flags" that > example, here are some of the more common uses for auxtypes: AppleWorks files: the auxtype contains information about the upper ( and lower case values of the filename.N Binary files: the auxtype contains the default load address when $ Basic.System does a BLOAD or BRUN.O Text files: the auxtype contains the record size and is used as / a flag for sequential or random-access files. LThe only use that Metal makes of the auxtype is the same that most programs M Kuse for Text files - that is, the auxtype is the length of the record size M Kand is used by the Recnum and Position commands to figure out where in the * file Metal should be at for each record. LThe value of a file's auxtype ranges from 0 to 65535 - in a ProDOS or Metal P Ncatalog, this is shown in it's hexadecimal value, so the value would be shown ranging from $0000 to $FFFF. LNote that Metal will never allow you to change the auxtype of a Directory P Nfile - you may read this value, but unless some other program has changed the O Mauxtype of a Directory file (which Apple frowns on), the returned value will always be zero. IEvery time you use FILEAUXTYPE, you may either supply a filename$ or a O file device number. Note that FILEAUXTYPE doesn't use the "default" Device @ value - if you wish to use this, you have to do the following: result=FILEAUXTYPE(Device) JIn order to use a file device , the file must currently be open. Using a D filename$ can be used whether the file is currently open or not. MSee also: CREATE, CLOSE, DELETE, DEVICE, DOSERR, FCOPY, FILEINFO$, FILEMARK, F DFILESIZE, FILETYPE, FLUSH, INPUT, ONLINE$, OPEN, POSITION, PREFIX$, PRINT, RENAME, RECNUM FILEINFO$ Type: system value result$ =FILEINFO$( filename$ i$=FILEINFO$("/hd1/prodos") print FILEINFO$(f$) KFILEINFO$ is used to gather information about the filename$ supplied. It N Lreturns either a null string or 79-character long string, which may then be operated upon or Printed out. EIf the filename$ value passed to FILEINFO$ doesn't actually exist, + FILEINFO$ will return a null string back. This result$ looks exactly like the Basic.System ProDOS catalog line. 1 2 3 4 5 6 7O M12345678901234567890123456789012345678901234567890123456789012345678901234567 M*PRODOS 11/10/89 01:15 11/05/89 17:46 15485 CIBS 12/20/90 06:45 11/16/90 14:16 1024 M*BBS 1015 00/00/00 00:00 11/16/90 14:16 2048 MThe first character of the result$ is either a space or an asterisk ("*"). N LAn asterisk stands for a "locked" file (one that cannot be rename, deleted, N or written to), and a space stands for a unlocked (one you can mangle) file. locked=left$(FILEINFO$(file$),1)="*"C [locked will be either zero (unlocked) or one (locked)] NCharacters 2 through 16 (15 characters long) is the filename portion stripped B from the filename$ value. It is always returned in upper case. filename$=mid$(FILEINFO$(file$),2,15) NCharacters 19 through 21 are the three-character "filetype" representation of L Jthe file. Metal has about 50 filetype strings built in, most of which are O MGS-specific. If Metal cannot find a "match" (say, for filetype $EE), then it 4 will return the filetype in hex ($EE or $B9, etc). type$=mid$(FILEINFO$(file$),19,3) LCharacters 24 through 28 is the number of blocks that the file uses. Spaces K Ipreceded this, but the Val command doesn't care - it will ignore leading E spaces. This value will be from 0 to 65535 (65535 blocks is 32megs) blocks=val(mid$(FILEINFO$(file$),24,5)) LCharacters 31 through 38 is the date the file was last modified in some way M K(data written to it, renamed, etc). If no date is available for this, then "00/00/00" is returned. lastmoddate$=mid$(FILEINFO$(file$),31,8) MCharacters 40 through 44 is the time that the file was last modified in some K Iway. If no time is available for this, then "00:00" is returned (this is O Mactual a legal time, but the chances of this being the real value are one in 1,440). lastmodtime$=mid$(FILEINFO$(file$),40,5) ICharacters 48 through 55 is the date the file was created. If no date is 2 available for this, then "00/00/00" is returned. createddate$=mid$(FILEINFO$(file$),48,8) NCharacters 57 through 61 is the time that the file was created. If no time is / available for this, then "00:00" is returned. createdtime$=mid$(FILEINFO$(file$),57,5) HCharacters 65 through 72 is the length of the file - like the number of H Fblocks, this is preceded with spaces. Note that this length is always P Npositive, even if the length goes past the +8meg limit Metal has built in. Of M Kcourse, the chances of a file actually being over 8megs long are slim - or , else you have a very large archive file. filelength=val(mid$(FILEINFO$(file$),65,8)) NCharacters 75 through 79 is the auxiliary filetype for this file, represented in hexadecimal value. auxtype$=mid$(FILEINFO$(file$),75,5)4 auxtype=hexval(mid$(FILEINFO$(file$),75,5)) LAnd finally, characters 17, 18, 22, 23, 29, 30, 39, 45, 46, 47, 56, 62, 63, 64, 73, and 74 are spaces. JThere is one vital difference between using FILEINFO$ on a filename and a L Jdisk volume - in our third example, "BBS" is actually a 3.5" disk volume. P NWhen this is done, the blocks used field is how many used blocks on the disk, N Land the auxiliary file type is the hex value of the total number of blocks. M KBy using this, you have an interesting way to determine how big the device ? is, how many blocks are in use, and how many blocks are free: a$=FILEINFO$("/bbs")8 totalblocks=hexval(mid$(FILEINFO$(file$),75,5))4 blocksused=val(mid$(FILEINFO$(file$),24,5))* blocksfree=totalblocks-blocksused JSee also: CREATE, DELETE, DOSERR, FCOPY, FILEAUXTYPE, FILEMARK, FILESIZE, 1 FILETYPE, INPUT, ONLINE$, OPEN, PREFIX$, RENAME FILEMARK Type: system variable result =FILEMARK( file device FILEMARK( file device value m=FILEMARK(1) FILEMARK(3)=z*100 if FILEMARK(1)=>filesize(1) then FILEMARK(1)=0 KThe FILEMARK command allows the program to either check where ProDOS is at N Lwithin a file and/or change that position - or "marker". Commonly, FILEMARK ; is used with the FileSize, Position, and Recnum commands. KThe value that FILEMARK returns to result or uses from value is a full I G24-bit integer value, thus the possible range is from -8meg to +8meg - C however, most of the time you will be using the 0 to +8meg value. KNotice that if you set the FILEMARK value of a file past the length of the L Jfile (FileSize), then Metal will automatically change the length of the K Ifile - thus, you can inadvertently create a "sparse" file that most copy & programs will have problems copying. KUsing FILEMARK requires that you currently have a the file device opened with the Open command. MThe value of FILEMARK that ProDOS uses is where in the file that ProDOS will O Meither get input from or place output to next - thus, every time a file is P Nfreshly Opened, the value of FILEMARK is set to zero, which means that ProDOS O Mwill begin reading or writing to the file starting at the beginning of that file KIf you set FILEMARK to the end of the file (by equating it to FileSize) or N Lpast the end of the file, then ProDOS will, if some form of output is done, P Nplace data at the of the file. If you remember the documentation on the B Append command, the following two lines are directly equivalent: FILEMARK(1)=FileSize(1) Append #1 GSee also: APPEND, BLOAD, BSAVE, CREATE, CLOSE, DELETE, DEVICE, DOSERR, A ?FCOPY, FILEAUXTYPE, FILESIZE, FILETYPE, FLUSH, INPUT, ONLINE$, D OPEN, POSITION, PREFIX$, PRINT, RENAME, RECNUM, RUN, RUNSUB, TCOPY FILENAME$ Type: system value result$ =FILE$( file device or string$ a$=FILENAME$(2). print "File channel 3 is using "FILENAME$(3) r$=FILENAME$("1/STARTUP.S")4 print "The full filename of "x$" is "FILENAME$(x$) NThe FILENAME$ variable is set by Metal to the filename of the file whenever a L Jfile is opened. This means that if you opened "2/user.data" on channel 3, O MFILENAME$(3) will contain "2/user.data" (actually, it will contain the fully O expanded ProDOS filename; it will look more like "/HD1/FV/SYSTEM/USER.DATA"). IIf you give FILENAME$ a string$ to operate on, Metal will "expand" the D Bfilename to it's full ProDOS pathname. Thus if you give FILENAME$ L "1/I/ACCESS.SUBS", FILENAME$ will return you "/HD2/FV/IEBS/I/ACCESS.SUBS". MYou can also give FILENAME$ the ".." command, and find out what the previous P Ndirectory was. For example, assume Prefix$ is set to "/RAM5/WORKDIR/TEMPDIR", J Hand you issue FILENAME$(".."): Metal will return "/RAM5/WORKDIR" as the P Nresult, since the ".." command will "peel" off the last directory in the name (see "Metal and Filenames"). KNote: FILENAME$(4) through FILENAME$(8) reflect the "system channels" that J Hare used internally. You should not need to read these values, as Metal G Edynamically allocates those file channels as the program runs; these B will not be the same from any one read of FILENAME$ to the next. JSee also: COMPILE, EDIT$, EXT, FCOPY, FILEACCESS, FILEAUXTYPE, FILEINFO$, 4 FILETYPE, FILESIZE, OPEN, RUN, RUNSUB, TCOPY, XFER FILESIZE Type: system variable result =FILESIZE( filename$ or file device FILESIZE( filename$ or file device value length=FILESIZE(z$) FILESIZE(z$)=val(i$)*10' if FILESIZE(1)>256 goto MoreThanAPage FILESIZE(1)==-91 NFILESIZE is used to either check the length of the file or to actually change O Mthe length of the file. Like FileMark, the value FILESIZE returns or uses is K I24-bits long, so it can go past the +8meg Metal integer limit and "wrap" around to a negative number. EFILESIZE is used generally to figure out how long it will take to do O something with a file, or to calculate the number of blocks a file will take. INotice that when you change the size of a file, you are doing one of two things: If you're extending the length, then you run the risk of creating a "sparse" file.I If you're shortening the length, then you are telling ProDOS to E Cpossible free up one or more blocks that the file previously used. 3 ProDOS takes a certain amount of time to do this. LNeither Metal nor ProDOS will allow you to change the length of a Directory / file. You may still read the length, however. GSee also: APPEND, BLOAD, BSAVE, CREATE, CLOSE, DELETE, DEVICE, DOSERR, C AFCOPY, FILEAUXTYPE, FILEINFO$, FILEMARK, FILETYPE, FLUSH, INPUT, @ >ONLINE$, OPEN, POSITION, PREFIX$, PRINT, RENAME, RECNUM, RUN, RUNSUB, TCOPY FILETYPE Type: system variable result =FILETYPE( filename$ or file device FILETYPE( filename$ or file device value a=FILETYPE("/hd1/selector.system")( if FILETYPE(2)=255 goto ItsAsystemFile FILETYPE(f$)=0 FILETYPE(1)=4 NThe FILETYPE command is used to read or change the "primary" file type of any O MProDOS file (with the exception of a Directory file). This file type is used N Ldifferently by different ProDOS applications - Metal doesn't care about the = file type of a file, with the exception of Directory files. GThe value of a file's type ranges from 0 to 255 - in a ProDOS or Metal C catalog, this is shown in it's ProDOS three-character identifier. NNote that Metal will never allow you to change the file type of a Directory O Mfile - you may read this value freely, but not change it. Nor can you change P Na file into a Directory file - the actual "file structure" of Directory files + are incompatible with non-Directory files FEvery time you use FILETYPE, you may either supply a filename$ or a L file device number. Note that FILETYPE doesn't use the "default" Device @ value - if you wish to use this, you have to do the following: result=FILETYPE(Device) JIn order to use a file device , the file must currently be open. Using a D filename$ can be used whether the file is currently open or not. ESee also: CREATE, CLOSE, DELETE, DEVICE, DOSERR, FCOPY, FILEAUXTYPE, > "; loop GET MODE(1) a$1 if a$="?" print "Help!":goto ShowHelp; if a$=chr$(8) print "Left Arrow":goto LeftArrow goto Loop KNote that like Input, GET clears the Abort$ value, and it also affects the Input Buffer data. JAlso note that the GET command from Device #0 will, unless you explicitly M Ktell it otherwise, filter out the control-S and control-Q keys (these keys O Mare normally used to pause and restart text display). Since it is very often O Mthat you don't wish to fiddle around with these control characters, GET will P Nautomatically "eat" them - each time one or the other is gathered by GET, the K Iroutine will simply ignore the control-S or -Q and loop back looking for more. MIf .degmode get X is used in the source of a program, Metal will use the "x" O Mvalue as the default GET Mode value. Normally, Metal defaults to Mode 0, but N Lmost BBS system reset this default on a program-by-program basis to default - into Mode 1 (lower to upper, no echo back). IIf you wish to use the default GET mode, and still use the filtering and I cr=this strings, you may omit the option, from the list. For example: GET MODE("YNQ","Y") I$ LWill use the current GET Mode default, but will allow the YNQ filter string to be used. See also: ABORT$, CLEAR, INPUT, PRINT, SYSINFO GOTO Type: flow control command GOTO label GOTO LogUserOff if money=0 GOTO OutOfCash on x GOTO Menu1,Menu2,Menu3 trap syserr GOTO SystemError IThe GOTO command will be one of your heaviest used commands under Metal. P NWhile it is certainly possible to write a program without using a single GOTO M Kcommand, doing so would be more an exercise in machismo than one in common sense. MThe GOTO command can be used by itself, within an If-Then-Else, from a Trap, M Kor the On-X flow controls. It is most commonly used within an If-Then-Else structure, however. MWhat the GOTO command does is change where the program is running at - Metal . switches from one place and "gotos" another. KUsing a GOTO is simple - you just follow the command with the label that N Lyou wish to pick execution up at - like LogUserOff, ShowHelpFile, etc, etc. For example: GOTO ShowHelpFile9 ...maybe some code that isn't executed... ShowHelpFile! tcopy "help.file" See also: FOR, IF, GOSUB, LONG IF, ON, PUSH, NEXT, THEN, TRAP, UNTIL, WHILE GOSUB Type: flow control command GOSUB label parms GOSUB label parms returns GOSUB GetInput if hit=1 GOSUB Ouch' on c GOSUB Display1,Display2,Display3 trap doserr GOSUB ShowDosErr GOSUB Function(name$) GOSUB Function(7,s$,val(x$)) GOSUB Function(zx)(ry) GOSUB Function()(l,a$,r$) KThe GOSUB (GOto SUBroutine) command is used in conjunction with the Return G Ecommand - what GOSUB does is very much like the GOTO command, but it ? remembers where Metal was at when the command was executed. MYou use the GOSUB command much like a GOTO command, but you must remember to K I"exit" a Subroutine using the Return command, like the following example shows: GOSUB ShowName" Goto SomePlaceElse ShowName* print "Your name is "name$ Return IBy adding the optional parenthesis after the label name, you are letting J Metal know that you wish to pass the parms to and/or from the routine. KPlease refer to the section on Local Variables for more information on the E structure and usage of GOSUB's with parenthesis (function calling). MSee also: FOR, IF, GOTO, LONG IF, ON, PUSH, NEXT, RETURN, THEN, TRAP, UNTIL, WHILE, Local Variables PQRSTUVWXY O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== Metal Commands : Section "A" Metal Commands : Section "H" Page HEXSTR$ Type: string function result$ =HEXSTR$( value flag a$=HEXSTR$(32768). print "The hex value of "mn" is "HEXSTR$(mn) b$=HEXSTR$(x,3)) print "The last 3 nibbles of "x" is "b$ x$=HEXSTR$(w,4,1) MHEXSTR$ (Hex String) is a string function designed to operate in conjunction M Kwith the HEXVAL operation. What HEXSTR$ does is take the value given and J Hturns it into a 7-character-long string of hexadecimal values (that is, ) digits ranging from 0 to 9 and A to F). MThe first character of the string will always be the "$" character - this is N Lwhat Metal uses as a standard "hex string flag" in it's CIB files. The rest J of the string - 6 characters - is the hexadecimal equivalent of value KEach of the 6 characters is a hexadecimal (hereafter referred to as "hex") J number - hex being base 16, as opposed to what we normally use, base 10. KFrom left to right (or the 2nd character to the 7th), the value of each of I the digits decreases by division of 16. The following table shows this: HEXSTR$ result: $xxxxxx! -------! 164211 05056 4596 For example, let's say we display the value of the above example: x$=HEXSTR$(32768) x$ will be "$008000" ILike BitStr$, HEXSTR$ will allow you to override the default 6-character result with the "$" lead-in. LSee also: BITSTR$, CHR$, CNGCASE$, FILEINFO$, LEFT$, MID$, REPEAT$, RIGHT$, STR$ HEXVAL Type: math function result =HEXVAL( bitstring$ access=HEXVAL(a$)/ print "the value of the string is "HEXVAL(x$) IHEXVAL is the converse of HEXSTR$, of course. What it does is take a bit L Jstring (of any length, from 0 to 255 characters long) and convert it into N Lit's numerical equivalent. The leading "$" character that HEXSTR$ places on M Kits output string is not required - it may be there or not, HEXVAL doesn't care. HEXVAL will stop converting the string when it: runs out of characters@ the character is not "0" through "9" or "A" through "F" NNote: depending on the size of the string that is converted, the result may or may not be negative. HSee also: ASC, BITVAL, INSTRING, LEN, MEMAREA, MEMSIZE, PEEK, PEEKADDR, D PEEKBYTE, PEEKWORD, PADDLE, RANDOM, ROTL, ROTR, SIGN, SYSINFO, VAL HIDE Type: command HIDE {RETURN} HIDE HIDE RETURN GThe HIDE command is used to in two ways - to duplicate off the current > variables in use or to save off the gosub/push/return stack. LThe first syntax - HIDE by itself - duplicates off the current variables in O Muse into a new memory area. It "steals" this memory from the Variable Memory J HArea, so a following Free after a HIDE will show a drastic reduction in memory available. NThis has the effect of having a copy of the variables being used. All further H Fvariable interaction will take place using this copy - the original variables are used. JUsing this, you could change your handle, password, etc, and then a later N LUnhide will recover the previous variables and remove the current list from O Muse. This means that you can do a HIDE, play massive damage to the variables L Jin use (including Clearing them), and then Unhide the image - and it will & appear as if nothing has happened. LThe second syntax of HIDE is using the RETURN optional after it. This Hides N the Gosub/Push/Return stack off. After a HIDE RETURN, several things happen: 1. The current Gosub-Return stack is inaccessible L2. There appears to be no Returns on the stack - at least, none that will work.L 3. The stack is reduced by however many Gosub-Returns you had stacked off. KTo recover from a HIDE RETURN, you simply do an Unhide Return, which kills O off whatever Returns you have and replaces them with the ones you Hid before. KNote that HIDE will not do anything (not even report an error) if there is J Hnot enough memory to store things off. HIDE RETURN will always HIDE the I GReturn stack, but if there is little or no room left in the stack, any ? following Gosub's will crash the system with an system error. See also: RUN, RUNSUB, RUN RETURN, UNHIDE [\]^_`abcdefghijklmnopqrstu O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== See also: ABORT$, CLEAR, CR, DEVICE, GET, PRINT, SYSIN Metal Commands : Section "I" Page Type: logical flow command condition_is_true {THEN} commands {:ELSE commands IF life=0 THEN goto YourDeadL IF bit3(x) and (name$="Wilson") print x*j/byte8(x):ELSE print x*j/byte2(j) MThe IF is one of the most commonly used commands in Metal (and in most other K Ilanguages, for that matter). Using the IF command (and the optional ELSE 7 command) allows you to setup conditional programming. NFor example, say that you are going through a for-next loop from 1 to 50, and E every time you get to a multiple of 5, you want to print a dot out: for j = 1 to 50 IF j mod 5 = 0 print "." next MBut what if you want to print a dot out every number multiplies of 5 - = you want to print out asterisks instead? Okay, easy enough: for j = 1 to 50+ IF j mod 5 = 0 print "*":ELSE print "." next EWhat we did was modify the IF command line by saying, in effect, the following: N "If the remainder of J divided by 5 is zero (ie: J is a even multiple of 5), M Kprint out an asterisk. However, if the remainder wasn't zero (ie: J is not 3 an even multiple of 5), print out a dot instead." FUsing the If-Then is relatively simple. There are just a few rules to remember: L1) Starting with the IF command, and to the end of that line , the rest of E Cthe line is considered to be the If-Then line, and will be treated specially. N2) If the condition_is_true expression evaluates to zero (ie: the numerical K Iexpression of the condition is mathematically zero), then the command(s) 8 following the optional THEN command will be run. M3) If the condition_is_true expression evaluates to a non-zero value, then C the command(s) following the optional THEN command will be run. M4) If the optional ELSE command is not in the If-Then line, then all happens as expected. M5) If the optional ELSE command in the If-Then line, then the following two rules apply: N5a) If the value of condition_is_true was zero, then the commands following the ELSE will be run. J5b) If the value of condition_is_true was -zero, then the commands ) following the ELSE will be run. NIt does seem rather complex if this is your first foray into programming, but N it's not too difficult - Metal is very forgiving using the If-Then commands. MNotice that Metal doesn't care if you use Then in the If-Then or not - Metal O Mis "smart" enough to figure out what you mean either way you go. You can put 2 Then in the program, of course - it's up to you. Programming notes: LYou can nest the If-Then with or without the LongIf-Then up to a maximum of P Neight (8) times. However, the Gosub command is handled specially in that each C Gosub/Return is treated as if they have their own If-Then "nest". The Goto command is handled as follows: If-Then: ends the If-Then/ LongIf-Then: does end the LongIf-Then HSee also: CLEAR, ELSE, END, LONG IF, FOR, GOTO, GOSUB, NEXT, POP, STEP, THEN, UNTIL, WHILE INPUT Type: complex command BINPUT { #device {,}} {MODE( mode$ )} {[ allow$ ]) {LEN( maxlen )} C prompttext "} {( prompt$ )} {CR} {([ echoback$ ])} variable {TO{,}} {, or CR} { variable(s) INPUT i$ INPUT #1,a$ INPUT #2 a$ cr b$ cr d,os$ INPUT mode ("UE ") i$ INPUT len(8) a$3 INPUT "Enter your name: " len(32) mode("U") name$ INPUT cr (pr$) zx$> INPUT "Enter password: " len(16) mode("UN ") (["?!@"]) pass$ INPUT ["123456789#-+"] i$ INPUT mode("0A") ["#-+"] i$ INPUT #1,a$(1) to a$(9) LWhen we say "complex command", we're not kidding - INPUT is one of the most M Khorrifyingly complex commands that Metal has to offer, with up to twelve optional parameters. NAs you can see by the examples, INPUT allows you extreme control of what kind P Nof data to input, where to get it from, how much to get, etc. Everything from P Nforcing the input from the keyboard into uppercase to inputting an array from a disk file. NOne at a time, here are the optional parameters. Note that for the most part, D the actual order of the parameters in the program is not a factor. Parameter Does --------- ---- #device By using this, you are telling the INPUT command to take < :input from some place other than the default Device value : 8(normally, this is zero, but you can change this if you > <- it is suggested that you do so, just to make your program code clearer to others. LMODE( mode$ The MODE optional allows you to change the pre-processing = ;done on typed text from the user - it has effect on > variable is optional, you must have at least one in the INPUT command!G If the variable is a string, then INPUT will use < :whatever it got as input from the device (either the user / or a file device) and place it in the string.M If the variable is a integer, then INPUT will take the 9 value of the typed/read string, similar to using the Val(string$) command. variable2 A comma after the first variable tells the Input command = ;to process the typed line in manner such that it splits up ; 9the data so that the first part is before the comma, the ; 9second after the comma, etc. (You can have more than two 1 variables in an INPUT line separated by commas) ICR variable2 Using the CR command to separate variable s tells the > if INSTRING("@",name$) print "You can't use @ in your name!" x=INSTRING("*SHK",fn$,"*") NINSTRING is one of the commands that return a numerical value based on string H data. In the case of INSTRING, the result is a number from 0 to 255. HWhat INSTRING does is takes a look at the searchthis$ and sees if the O Mstring given for findthis$ is somewhere in it. INSTRING doesn't care about G Ethe "case" of the strings - it converts both strings, internally, to N Lupper-case before performing the search. After INSTRING finishes looking at . the strings, it returns a value to result NIf the value of result is zero, then INSTRING couldn't find the findthis$ inside of searchthis$ KIf the value of result is not zero, then INSTRING able to find the P findthis$ inside of searchthis$ , and that value returned is the character ' number into the searchthis$ string. For example: print INSTRING("AP","APPLE") result is 1 - first character of APPLEI print INSTRING("ap","GRAPE") result is 3 - 3rd character of GRAPEA print INSTRING("AP","Pear") result is 0 - AP not in PEARA print INSTRING("ap","tree") result is 0 - AP not in TREE As you can see, the upper/lower case of either string is not important. LINSTRING also supports a "wildcard" mode, similar to what the Unix language O Mhas for string matching. To use this wildcard mode, you must supply INSTRING K Iwith the character it is to use. Normally, you will be using "*" or "=", K Isince they are the ones used in most other systems. However, you can use whatever character you wish. LIn the wildcard mode, the result is either 1 (match found) or 0 (no match found). KIf the findthis$ is only one character long and is the wildchar$ , then B the INSTRING will, of course, return a value of 1 - match found. Examples: print INSTRING("*SHK","core.shk","*") result is 1 - SHK is the last three characters.L print INSTRING("*SHK","core.bxy","*") result is 0 - SHK is not the last three characters.N print INSTRING("*SHK","core.shk1","*") result is 0 - SHK is the " - last three characters (although " does appear in the string).L print INSTRING("C*","core.shk","*") result is 1 - C is the first character.L print INSTRING("C*","scores.shk","*") result is 0 - C is the first character (although is does appear in the string).M print INSTRING("*.*","core.shk","*") result is 1 - "." does appear in the string.M print INSTRING("*SHK*","core.shk",*") result is 1 - SHK does appear in the string.M print INSTRING("*SHK*","core.shk1","*") result is 1 - SHK does appear in the string. KSee also: ABS, ASC, BITVAL, HEXVAL, LEN, MEMAREA, MEMSIZE, PEEK, PEEKADDR, D PEEKBYTE, PEEKWORD, PADDLE, RANDOM, ROTL, ROTR, SIGN, SYSINFO, VAL wxyz{|}~ O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== See also: BITSTR$, CHR$, CNGCASE$, FILEINFO$, HEXSTR$, Metal Commands : Section "L" Page LEFT$ Type: string function result$ =LEFT$( string$ length q$=LEFT$(a$,15) name$=LEFT$(name$,mx)" if LEFT$(i$,1)="Q" goto QuitBack NThe LEFT$ function allows you to "trim" a given string down to so-and-so many O Mcharacters. This is useful for several things - such as limiting a string to P Nsay, 15 characters, or checking just the first character of a string for some sort of match. HWhat LEFT$ does is take the given string$ parameter and use the first J length number of characters (from the left, as it seems). For example: Wilson [ 6 characters long ]? LEFT$("Wilson",3) [ take the first or "left" 3 characters ], Wil [ the result is this ] NHowever, there is a special clause to the LEFT$ operation: if the length is P Ngreater than the total number of characters in the string$ to be used, then L JLEFT$ can only return the original string$ ! The following example shows this: Tc Wilson [ 9 characters long ]> LEFT$("Tc Wilson",20) [ want the first 20 characters....]O Tc Wilson [ but 20>9, so we can only use the original string ] FSee also: BITSTR$, CHR$, CNGCASE$, FILEINFO$, HEXSTR$, MID$, REPEAT$, RIGHT$, STR$ LEN, **Type: math function based on string data result =LEN( string$ option x=LEN(a$)4 if LEN(q$)=0 print "You've gotta enter something!" r=LEN(i$,1) LThe LEN (short for LENgth) returns the number of characters (the length) of N Lthe given string$ . If the given string$ is null, then LEN will return a H Fvalue of zero. Any other value from 1 to 255 means that the string is ! so-and-so many characters long. NIf you give LEN a value of 1 for option , LEN will ignore control characters O Min the string; this is useful when printing strings that have buried control P Ncodes in them and you need to know how many printing characters will actually be shown. FSee also: ABS, ASC, BITVAL, HEXVAL, INSTRING, MEMAREA, MEMSIZE, PEEK, B @PEEKADDR, PEEKBYTE, PEEKWORD, PADDLE, RANDOM, ROTL, ROTR, SIGN, SYSINFO, VAL LONG IF Type: logical flow command LONG IF condition_is_true commands_if_true {ELSE commands if false END IF LONG IF name$="Tc Wilson"1 print "Welcome sir, to our wonderful system!" tl=0:byte2(9)=1:sysf=1. print "You have massive access this call!" ELSE, print "Welcome, "name$", to our system!"$ tl=byte1(1)*60:byte2(9)=0:sysf=0, print "You have "tl" minutes this call!" END IF GLONG IF is an extension of the standard If-Then command. Like If-Then, K ILONG IF executes commands based on the result of the condition_is_true expression. KUnlike the If-Then command, LONG IF allows you to place more than a single E Cline into the commands to do - this is handy when you have a large H condition_is_true expression, or when you have a lot of commands to # processes based upon that result. JLONG IF's syntax is very simple and is a logical extension of the If-Then O Mcommand. What you do is place the expression to be checked after the LONG IF N L(or LONGIF or LONG IF - spacing is unimportant, but they must follow each O Mother - LONG OR IF won't work, for example), start a new line, and place the N Lcommands you want executed, as many as you want, as many lines as you want. N LYou can even place labels within this "block" of code, and have things such L Jas For-Next loops, If-Then-Goto loops, Do-While, While-EndWhile, etc, all O Mwithin this block of code. You can even nest multiple LONG IF's together, up to about 6 levels deep. LAfter your block of code, you must tell Metal where the LONG IF ends at - N Lunlike the normal If-Then, where the end of the line implied the end of the M KIf-Then, the LONG IF requires that you place an END IF at the end of the block of code. NThe ELSE command if fully optional, and should be on a line by itself, as the above example showed. NRemember, GOTO's are handled specially under LONG IF's - the LONG IF is still O M"active", and you must tell Metal not to think it's running under an LONG IF = conditional any more. Handle this minor problem as follows: LONG IF a=0. print "Yoiks!": pop if :goto DeadMeat END IF FThe reason for this is the above-mentioned "loop-back" coding, as the following example shows: LONG IF page=2 label# print "Press the RETURN key:"; get a$ if a$<>chr$(13) goto label END IF CIf Metal were to clear out the current LONG IF whenever a Goto was M Kencountered, it would make coding such a thing as the above impossible. So P Nthe trade-off to allow this requires you to place a Pop If before a Goto that . prematurely exits the LONG IF-END IF coding. ISee also: CLEAR, ELSE, END, FOR, GOTO, GOSUB, IF, NEXT, POP, STEP, THEN, UNTIL, WHILE O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== MODEM(2): Baud Ratete dividend _mainder RD, WORDDR, Metal Commands : Section "M" Page MAKEWORKFILE( return$ dir$ MAKEWORKFILE(f$)# MAKEWORKFILE(a$,"4/PRIVATESPOOL") MAKEWORKFILE(xq$,fn$) JMAKEWORKFILE is a built-in "procedure", similar to the SMF commands. What N LMAKEWORKFILE does is creates a new, blank, typeless (filetype of 0, auxtype M Kof 0) in either the 9/ directory (if the dir$ optional is missing) or in the directory given in dir$ LIf the string given for dir$ actually points to an existing non-directory L Jfile (say, for example, you give it as 0/METAL.SYSTEM), MAKEWORKFILE will O Mmake the new workfile in that directory - thus it will return the workfile " return$ as "0/WKF.1234568". IMAKEWORKFILE always returns back the full, expanded filename of the file G Ecreated - thus it will return back "/RAM5/WORKDIR/WKF.00004191", not "9/WKF.00004191". See also: CREATE, DELETE, OPEN, SMF commands MCLEAR Type: command MCLEAR start TO value FOR length MCLEAR byte1 TO 0 for 256+ MCLEAR memarea(10) TO $80 FOR memsize(10) HMCLEAR (Memory CLEAR) simply lets you wipe a given range of memory to a K Icertain value. It is very simple to use: the start value is the memory M Kaddress to start wiping at (byte1 or memarea(10) for examples), value is M Kthe 0-255 number to erase the range to (normally, 0 is used for this), and & length is how many bytes to erase. LNotice that MCLEAR treats the value as if it is 0-255, no matter if it is L J-1 or 1982 or whatever. Also, the length value is the total number of N Lbytes of memory to erase, not from start to start length - the actual N Larea wiped is start to start length - the following math explains this more clearly: length =5, start =8192, End=8192+5=8197.. Wrong. You're clearing the following:A 8192 8193 8194 8195 8196 8197 - 6 bytes, not 5. length =5, start =8192, End=8192+5-1=81960 Correct. You're clearing the following:: 8192 8193 8194 8195 8196 - 5 bytes. FSee also: ADDR, ALLOCATE, BIT, BLOAD, BSAVE, BYTE, DEALLOCATE, MCOPY, B @MEMAREA, MEMSIZE, MEMSTRING$, NIBBLE, PEEK, PEEKADDR, PEEKBYTE, 4 PEEKWORD, POKE, POKEADDR, POKEBYTE, POKEWORD, WORD MCOPY Type: command MCOPY source TO target FOR length MCOPY memarea(12) TO temp FOR 2562 MCOPY msg(msg,2)*16 TO ram9 FOR 1600+filesize(2) KMCOPY (Memory COPY) is a built-in command that lets you copy (duplicate) a I Grange of memory into another range of memory. The MCOPY command can be 6 consider the same as the following program fragment: for j = 0 to length -1 step 1& poke source +j,peek( target next NMCOPY can be useful if you're into doing elaborate programs where you have to M Kduplicate, say, the current user's profile into a working area. MCOPY will ; copy all bytes in the range, regardless of what is there. LA programming note here: if the given source and target address are set N Lup in the correct order, it is possible to screw things up nicely - instead P Nof copying data as you would wish, you will get the first, say, four bytes of G data repeated over and over again. The following fragment shows this: MCOPY 8192 to 8193 for 256 KWhat happens here is that the byte at location 8192 is copied to 8193, and I Gthen the byte at location 8193 is copied to 8194, etc - thus, you have L Jnothing but the original value of the byte at 8192 repeated over and over again! GSee also: ADDR, ALLOCATE, BIT, BLOAD, BSAVE, BYTE, DEALLOCATE, MCLEAR, B @MEMAREA, MEMSIZE, MEMSTRING$, NIBBLE, PEEK, PEEKADDR, PEEKBYTE, 4 PEEKWORD, POKE, POKEADDR, POKEBYTE, POKEWORD, WORD MEMAREA Type: system value result =MEMAREA( value x=MEMAREA(7)! mclear MEMAREA(msg) to 0 for 16 JThe MEMAREA command ties directly in with the Allocate command - Allocate O Mfinds and assigns a memory area, and MEMAREA retrieves the starting location of that area. LUsing MEMAREA is simple - you simply give it the area number ( value ) that L Jyou wish to find out about, and it returns a memory address, ranging from 8192 to 32767. HIf MEMAREA returns a zero value, then that particular area number isn't N LAllocated. The following program listing gives a routine that will list all % the current Allocated memory areas: for j = 1 to 127< if MEMAREA(j)<>0 print "Area "j" starts at "MEMAREA(j) next HMEMAREA will only crash with an Range Error if the value given is not within the range of 1 to 127. GSee also: ADDR, ALLOCATE, BIT, BLOAD, BSAVE, BYTE, DEALLOCATE, MCLEAR, @ >MCOPY, MEMSIZE, MEMSTRING$, NIBBLE, PEEK, PEEKADDR, PEEKBYTE, 4 PEEKWORD, POKE, POKEADDR, POKEBYTE, POKEWORD, WORD MEMSIZE Type: system value result =MEMSIZE( value x=MEMSIZE(7)+ mclear memarea(msg) to 0 for MEMSIZE(msg) KThe other half of Memarea is the MEMSIZE command - whereas Memarea returns P Nthe starting location of a particular memory area, MEMSIZE returns the number % of bytes that the memory area uses. NWhen you use the Allocate command to parcel out memory for a memory area, you M Kgave it a parameter that told Allocate how many bytes that you wanted. For N Lthe most part, you will always know how big that area is, but there will be M Ktimes when you are doing radical programming that will require the size of O the Allocated area to shrink and grow. This is where MEMSIZE comes into play. KLike Memarea, using MEMSIZE is simple - you simply give it the area number O value ) that you wish to find out about, and it returns the length of that & area, ranging from 0 to 24576 bytes. HIf MEMSIZE returns a zero value, then that particular area number isn't N LAllocated. The following modified program listing of the above routine will E list all the current Allocated memory areas, and the sizes of each: for j = 1 to 127 long if memarea(j)<>0M print "Area "j" starts at "memarea(j)" and is "MEMSIZE(j)" bytes long." next HMEMSIZE will only crash with an Range Error if the value given is not within the range of 1 to 127. GSee also: ADDR, ALLOCATE, BIT, BLOAD, BSAVE, BYTE, DEALLOCATE, MCLEAR, @ >MCOPY, MEMAREA, MEMSTRING$, NIBBLE, PEEK, PEEKADDR, PEEKBYTE, 4 PEEKWORD, POKE, POKEADDR, POKEBYTE, POKEWORD, WORD MEMSTRING$ Type: command/string function result$ =MEMSTRING( address length MEMSTRING$( address length string$ MEMSTRING$(temp)=name$ MEMSTRING$(uf,32)=hand$' print "Your name is "MEMSTRING$(temp)* print "Your handle is "MEMSTRING$(uf,32) NMEMSTRING$ is used to place a given string or string expression into a memory @ location, or to read a previously placed string out of memory. NMEMSTRING$ is set up to allow you two slightly different storage formats: the J Hfirst format, used when the , length optional is not given, places the O Mlength of the string into memory, followed by the string itself. This is the J normal storage format that ProDOS and GSOS use to store their filenames. MThe second storage format is used when you give the , length optional - you N Lare telling MEMSTRING$ that the string is so-and-so characters long, and to N use the first byte as the length. This is useful if you want to limit ( the size of a string to 32 characters. The following examples clearly illustrate the effects of each storage format: MEMSTRING$(8192)="Tc Wilson"1 8192: 009 9 characters long# 8193: 084 "T"# 8194: 099 "c"# 8195: 032 " "# 8196: 087 "W"# 8197: 105 "i"# 8198: 108 "l"# 8199: 115 "s"# 8200: 111 "o"# 8201: 110 a$=MEMSTRING$(8192)5 A$ will be 9 characters long: "Tc Wilson" MEMSTRING$(8192,4)="Tc Wilson"# 8192: 084 "T"# 8193: 099 "c"# 8194: 032 " "# 8195: 087 a$=MEMSTRING$(8192,4)0 A$ will be 4 characters long: "Tc W" MEMSTRING$(8192,4)="Tc"# 8192: 084 "T"# 8193: 099 "c"6 8194: 000 extras padded to nulls6 8195: 000 extras padded to nulls a$=MEMSTRING$(8192,4). A$ will be 2 characters long: "Tc" a$=MEMSTRING$(8192) [whoops?], A$ will be 1 character long: "c" IThe last example was given to show what would happen if you accidentally N Lmixed the wrong retrieval with the wrong storage: since you explicitly told J HMEMSTRING$ to store off the length of the string into memory, the G Eretrieval must also use this - however, you told it to use the first N Lcharacter of the memory as the length of the string that follows - in other N Lwords, expect a string that is 84 characters long to follow. However, since P Nyou tried to store a 2-character string into a 4-byte area, MEMSTRING$ padded O Mout the last 2 bytes to zeros - and MEMSTRING$ balked at trying to read that back out. GSee also: ADDR, ALLOCATE, BIT, BLOAD, BSAVE, BYTE, DEALLOCATE, MCLEAR, = ;MCOPY, MEMAREA, MEMSIZE, NIBBLE, PEEK, PEEKADDR, PEEKBYTE, 4 PEEKWORD, POKE, POKEADDR, POKEBYTE, POKEWORD, WORD MID$ Type: string function result$ =MID$( string$ index length a$=MID$(i$,4,1)' if left$(z$,1)=" " then z$=MID$(z$,2)) if val(MID$(date$,7,2)<>91 goto Not1991 GThe MID$ function is used to report back characters within the given N string$ . This can be used in myriad ways, from checking the 3rd character 8 over to stripping the first character out of a string. Normally, the length optional is used - it is rare that it is used. KThe way MID$ functions is rather straightforward: you give it two or three P Nparameters - the string$ to look at, the character index into the string, < and how many characters back (the length ) that you want. For example, let's take a look at the following program fragment: a$=MID$("Tc Wilson",1,2) MThe string$ to be operated on is Tc Wilson , and the index value is 1 - L Jthe first character of the string, and we want a length of 2 characters N back. Thus, A$ will be equal to - the first 2 characters of the string. a$=MID$("Tc Wilson",4,4) KHere, we are still looking at Tc Wilson , but we want to start looking at J Hthe 4th character into the string - "W" - and we only want 4 characters * output. Thus A$ will be equal to Wils a$=MID$("Tc Wilson",4,20) INotice in this example that the length is 20 characters long - but the O Mentire string is only 9 characters long! This is the same as the 4,4 example P Ndirectly above - but what will A$ be equal to? It will be equal to Wilson that's all. KWhy is this? Well, MID$ got the length value, and saw that you wanted to H Fstart accessing the Tc Wilson string at the 4th character (the "W", M Kremember?). Since the rest of the string - Wilson - is only 6 characters , long, it only used characters, not 20! Now let's see some examples that don't use the length optional: a$=MID$("Tc Wilson",4) MA$ will be equal to Wilson - the same as the previous two examples. Why is N Lthis? Well, if MID$ doesn't get the length operation, it assumes that you O want the string starting at the index character to the end of the string Rules for usage of MID$: If the index value is larger than the string$ is (say you want the M K50th character, and the string is only 20 characters long), then MID$ will return a "null" string.I Go If the length optional is absent, then MID$ will return the string ! starting at index to the end.O Mo If the length optional is larger than the possible resulting string (say M Kyou asked for 50 characters from a 60 character string, but you started at N Lthe 40th character), then MID$ will only return as much of the string as it can.J If the index value is zero, then MID$ will always return a "null" string. GSee also: BITSTR$, CNGCASE$, CHR$, FILEINFO$, HEXSTR$, LEFT$, REPEAT$, RIGHT$, STR$ Type: math operand result dividend MOD divisor x=b1 MOD 7 if (j MOD 4)=0 print "."; MThe MOD math operand stands for Modulo - what this high-sounding word really E means is that MOD computes the remainder of the two values given. NIf you remember your basic math from school, you'll remember that two integer M Knumbers, when divided, always wind up with two results: the result and the O Mremainder. The math operand handles the result (5/2 will equal 2), while 3 MOD handles the remainder (5 MOD 2 will equal 1). result R remainder ________________ divisor / dividend For example, let's use the 5 MOD 2 above in the little diagram: 2 R ________________ NThe remainder or result of a MOD operation will always be less than the divisor See also: B.AND, B.EOR, B.OR, EOR, NAND, NEOR, NOR, NOT, OR, +, -, *, / MODE Type: buried command MThe MODE command is used in the INPUT, FCOPY, and GET commands, and may also O Mbe used in several external packages. The MODE command may be executed N Las a normal Metal command - it is always a "buried" command to flag certain optional parameters. See also: INPUT, FCOPY, GET MODEM$ Type: command MODEM$=i$ MODEM$="ATDT5551212" MODEM$="AT"+x$ KThe MODEM$ command is used to send commands directly to the modem driver - M Ksuch as a dial-out for a networking routine or a term program, or maybe to ( tell the modem to turn the speaker on. MNormally, this command is done to tell the system to dial out and connect up N Lwith another computer in order to "network" electronic mail back and forth, 2 but it can be used in whatever fashion you wish. KIf the string given to MODEM$ results in the modem connecting with another L Jsystem, then the MODEM(1) value will go to a "5" value, indicating that a " connection has been established. NYou should consult your modem's particular documentation for more information on this subject. See also: MODEM MODEM Type: complex system variable result =MODEM( function MODEM( function value baud=MODEM(2) MODEM(1)=4 JThe MODEM command is used to set things up with the modem or read what is going on. JThe following table lists out each of the possible six function values, L Jwhat the "name" of each is, and wether or not the function can be read or written: function name r/w- -------- ----------------- ---- Modem State r/w+ Baud Rate Nulls Sent r/w- LF added to CR r/w+ Modem Carrier Modem Result MODEM(1): Modem State LThe Modem State function is used to either set the modem up in some "state" O Mof operations - such as auto-answer, off hook, reset, etc. It may be read to 1 see if the modem has connected or lost carrier. MODEM(1)=0 This function will reset the modem, using the string 7 defined in the Metal.Config Script command MODEMINIT.O MODEM(1)=1 This will hang the phone up and disconnect the modem. It & uses the Script command MODEMHANGUP.K MODEM(1)=2 This will set the modem up for an auto-answer on the 2 next call. It uses the Script command MODEMAUTO.O MODEM(1)=3 This will tell the modem to try and generate a carrier - : 8basically, go from a voice chat into the modems talking 7 with each other. Uses the Script command MODEMGENCAR.K MODEM(1)=4 This will take the modem "off the hook" and have the < :phone companies lady yell at you. Uses the Script command MODEMOFFHOOK. Result of MODEM(1): MODEM(1)=0 through 4: last State executed.H MODEM(1)=5: The modem has gotten a good connection and is now 9 7online. Read the MODEM(2) value for the baud rate that the system is connected at.G MODEM(1)=6: The modem has "lost carrier" (read: the user has < :disconnected by shutting his modem off). This can also be ; 9synthesized by pressing the OpenApple-D control to force 2 the system to think that the user has done that./ MODEM(1)=-1: The modem driver is busy. Generally, you only need to check if MODEM(1) has gone to a value of 5. MODEM(2): Baud Rate KThis value (which you may only read) returns back the current baud rate of N Lthe connection. If there is no connection, then this will return a value of P N0; otherwise, it returns the baud rate. The following is a list of valid baud rates: 0 baud( 300 baud) 1200 1200 baud) 2400 2400 baud) 4800 4800 baud) 9600 9600 baud* 19200 19200 baud* 38400 38400 baud* 57600 57600 baud NNote: 4800 is displayed locally on the screen as "2400arq" and should be used F Dto distinguish between a standard 2400-baud connect and one that is D Busing one of the MNP-level data corrections. The "arq" comes from H Fstandard modem terminology, and refers to "Automatic Repeat Request", 6 and gives rise to the term "error-correcting modem". MODEM(3): Number of Nulls (chr$0's) sent with each CR (chr$13's) JThe function will allow you to read or set the number of "nulls" that the M Ksystem sends out each time a carriage return character (chr$13) is printed O Mout over the modem. Normally, this should be zero, as using a non-zero value ( will affect how fast the system works. MThis is generally used for term programs that have timing problems when they O Mhave to process the carriage returns - by adding null characters each time a O Mcarriage return is printed, it lets the BBS, in effect, "slow down" to match the user's term speed. MODEM(4): Add line feeds (chr$10) when printing CR's (chr$13's) NThis is a "flag" value - thus is can only be a value of 0 (off, no line feeds P Nsent) or 1 (line feeds sent). When this is 1, each time the system prints out O Ma carriage return, it also sends out a line feed. Most term programs require N La line feed with returns, because carriage returns only move the horizontal M Ktab to the left column, and the line feed will have to be used in order to ( move the cursor down to the next line. MODEM(5): Carrier signal check NThis is a read-only value, and is used just for your own amusement. It simple P Nreturns the current carrier state of the modem, returning a 0 if the modem is O Mnot connected to another modem, and 1 if the modem is connected with another J Hmodem. Some modems will also bring this value to 1 when they are in the P Nprocess of getting a carrier; this can be used in dialing routines to check P Nif the modem is in the process of getting connected - the program can then go into a very fast check-loop. MODEM(6): Modem Result Code HThis is also a read-only value. This function returns the current modem L Jresult code (say, 0 for OK, 10 for CONNECT 2400) from the low-level Modem I GDriver. Note that some modems may return different things - you should 9 consult your modem's manual for a list of result codes. MThis function is useful if you are networking and need to know if the remote $ system is "busy" or not answering. See also: MODEM$, TRAP, Script Commands O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== See also: AND, B.AND, B.EOR, B.OR, EOR, NAND, NEOR, NO Metal Commands : Section "N" Page NAND Type: logic operand result operand1 NAND operand2 z=x NAND y if wild NAND crazy goto nuts IThe NAND (Negative AND) command word is similar to the AND function - it P Ntakes the logical value of operand1 and operand2 and returns a value of 0 O Mif they are both not equal to zero; if either operand is zero, then NAND returns a 1 value. The NAND operation is functionally equivalent to the following: z = x NAND y same as: z = NOT (x AND y) LWhile the NAND function is not heavily used as the AND function is, it does : have its place, and can come in handy from time to time. NAND can be thought of as an logical "inverse multiplier": 1 - ( 0 x 0 ) = 1 1 - ( 0 x 1 ) = 1 1 - ( 1 x 0 ) = 1 1 - ( 1 x 1 ) = 0 MNote that the actual values of operand1 and operand2 don't really affect K Ithe outcome of the NAND command - it just cares if the values are either D zero or non-zero - non-zero values are treated as a "1" value. See also: AND, B.AND, B.EOR, B.OR, EOR, NEOR, NOR, NOT, OR NEOR Type: logic operand result operand1 NEOR operand2 z=x NEOR y@ if youdead NEOR hedead print "You're both dead or both alive!" IThe NEOR (Negative EOR) command word is similar to the EOR function - it P Ntakes the logical value of operand1 and operand2 and returns a 1 value if J Hthey are both the same logical value (both zero or both non-zero); it , returns a 0 value if they are different The NEOR operation is functionally equivalent to the following: z = x NEOR y same as: z = NOT (x EOR y) NEOR can be thought of as an logical "inverse subtracter": 1 - ( 0 - 0 ) = 1, 1 - ( 0 - 1 ) = 0 (sign is dropped) 1 - ( 1 - 0 ) = 0 1 - ( 1 - 1 ) = 1 MNote that the actual values of operand1 and operand2 don't really affect K Ithe outcome of the NEOR command - it just cares if the values are either D zero or non-zero - non-zero values are treated as a "1" value. See also: AND, B.AND, B.EOR, B.OR, NAND, NEOR, NOR, NOT, OR NEXT Type: looping command NEXT { variable for j = 1 to 10 .... NEXT for x9 = low to high .... NEXT x9 JThe NEXT command closes off the FOR-NEXT loop that the For command talked O Mabout. For each and every For, you must have a NEXT in order to complete the loop. KIf you don't supply the variable optional, the NEXT command will use the O Mcurrent "outside" For-Next loop - in other words, the last-used For command. J HThis makes "nesting" multiple For-Next loops possible without having to , consistently type-in the variable to step: for j = 1 to 50 for k = 1 to 60 print j,k# NEXT ! uses K# NEXT ! uses J KAs you can see, the first NEXT will use the K loop until the K exceeds the N Lvalue of 60, at which point the For-Next loop automatically terminates. The P Nsecond NEXT will use the J loop - at which point, the system does another K P Nloop. This continues, using one For-Next after the other, until J exceeds the value of 50. GIf you supply the optional variable , then you are forcing the NEXT Q Ocommand to use that For loop, prematurely terminating any loops that may exist P within the loop. Normally, you don't wish to do this, and will just use the N Lcurrent "outside" loop. The following two samples show what happens if each structure is used: 1) Normal usage, outside loop: for j = 1 to 50 for k = 1 to 50 print j,k next k next j This example functions the same as the one given above. 2) Specialized usage, terminate outside loop: for j = 1 to 50 for k = 1 to 50 print j,k next j next k In this example, the output printed will be nothing more than 1,1 F D2,1 3,1 4,1, 5,1, 6,1. At this point, because the NEXT J has forced F Dthe FOR K to re-execute before it was closed off and removed from D Buse, Metal will crash with a system error - FOR/NEXT STACK OVER LAs you can see, using the optional variable can get you into some serious O Mtrouble - it is not recommended to use this optional because of this, but if ; you must, then use caution and plan your moves carefully. LProgramming tip: if you must use this form of NEXT, in order to skip over a J Hcurrent loop, then try using POP NEXT or POP FOR in order to remove the K Icurrent outside loop. Generally, this would be within some heavy if-then logic. JSee also: CLEAR, DO, ELSE, END, FOR, IF, GOTO, GOSUB, LONG IF, POP, THEN, UNTIL, WHILE NIBBLE. Type: complex system variable/memory storage NIBBLE{ area index value or starting_base result or current_base =NIBBLE{ area index NIBBLE=memarea(9)+82 NIBBLE3=memarea(2) print NIBBLE2 NIBBLE1(3)=blks lngh=NIBBLE(20)/word2(7) MNIBBLE is a very specialized command that is used to manipulate memory areas in various ways. KNIBBLE "data chunks" are each 4 bits long - thus they can each only hold a P Nvalue of 0 to 15. If you try to equate a NIBBLE to a value greater than 15 or O Mless than zero, NIBBLE will perform a "modulo 16" operation on it (actually, it does a B.AND 15). NSince NIBBLEs can fit within a single byte of memory (4 bits per each NIBBLE, N L8 bits per each byte), NIBBLEs rank just under Bits as efficiency goes. But O Mthen again, you can store a larger number - instead of 0 to 1, you can store 0 to 15. JLike Bit, Byte, etc, NIBBLE may be given one of ten distinct and separate A memory "area" to work out of. These are the { area } optionals. FThe { area }, if given, is a single digit, ranging from 0 to 9. If no O area } is given, then it defaults into zero. Thus, the following are equal: NIBBLE=memarea(2)+82 NIBBLE0=memarea(2)+82 NThe { area must immediately follow the NIBBLE command word, otherwise you N Lwill cause rather odd things to happen in your code, depending on where you K Imade the mistake - the results could range from a Syntax Error to simply P Nhaving wrong numbers being printed out. There must be spaces between the NIBBLE and the { area JThe {( index )} optional tells Metal wether or not to set or retrieve the N L"starting base" for that NIBBLE area, or to set or retrieve a value in that I Garea. This breaks the NIBBLE command down into two distinct and very separate parts: K(a) If the {( index )} optional is missing, Metal assumes that you wish I Gto manipulate the starting base for the NIBBLE's area. By setting (ie: E Cequating NIBBLE{ area } to some value) you are telling Metal where G Ethat NIBBLE is living at and where to store or look for data at. The I Gvalue given will be assumed to be a 16-bit memory address. Likewise, G Ereading the NIBBLE{ area } will retrieve the last set value for that NIBBLE: NIBBLE=memarea(2)+82 this example sets up where NIBBLE area 0 - #+(the default, remember?) is going to start , #*at. The "memarea(2)" value was previously " setup using an Allocate command.O print NIBBLE this example displays where NIBBLE area 0 is currently coming from. E(b) If the {( index given, Metal assumes that you wish to H Fmanipulate the data inside of that NIBBLE area. Remember, each data H Felement - the "index" - is 1/2 of a byte long. The value of the index F Dmay range from 0 - the first element in the NIBBLE area - to approx 49,000. NIBBLE(2)=7 this example sets NIBBLE area 0, element number 2 to the value of 7.I NIBBLE3(0)=1 this example sets NIBBLE area 3, element number 0 to the value of 1.M print NIBBLE(9) displays the value of NIBBLE area 0, element number 9. KAs previously mentioned, NIBBLE elements occupy 1/2 of a byte per element. N LMetal automatically calculates where the element is at in the starting base N Lfor that area, so you don't need to mess with calculations. Again, the only N drawback to NIBBLE is that it can only store and retrieve values of 0 to 15. ISee also: ADDR, ALLOCATE, BIT, BYTE, DEALLOCATE, MEMAREA, MEMSIZE, PEEK, D BPEEKADDR, PEEKBYTE, PEEKWORD, POKE, POKEADDR, POKEBYTE, POKEWORD, WORD Type: logic operand result operand1 NOR operand2 z=x NOR y8 if uploads NOR downloads print "No transfer activity." LThe NOR (Negative OR) command word is similar to the OR function - it takes M Kthe logical value of operand1 and operand2 and returns a value of 1 if K Ithey are both equal to zero; if either operand is non-zero, then NOR returns a 0 value. The NOR operation is functionally equivalent to the following: z = x NOR y same as: z = NOT (x OR y) OWhile the NOR function is not heavily used as the OR function is, it does have 5 its place, and can come in handy from time to time. NOR can be thought of as an logical "inverse adder": 1 - ( 0 + 0 ) = 1 1 - ( 0 + 1 ) = 0 1 - ( 1 + 0 ) = 00 1 - ( 1 + 1 ) = 0 (1+1 is treated as 1) MNote that the actual values of operand1 and operand2 don't really affect J Hthe outcome of the NOR command - it just cares if the values are either D zero or non-zero - non-zero values are treated as a "1" value. See also: AND, B.AND, B.EOR, B.OR, EOR, NAND, NEOR, NOT, OR Type: logic operand result =NOT operand z=NOT x0 if NOT staff print "You're not a staff member" NThe NOT command (so heavily referred to in the above documentation) basically N L"flips" the logical value of operand and returns the inverse of it. Thus, K Iif the value of operand was zero, then NOT returns a 1; conversely, if C operand equated to a -zero value, then NOT returns a zero. LNOT is generally used in If-Then logic to check for certain access flags or P Nconditions. In most cases, the use of NOT and the equals/not equals signs can # be interchanged with no problems: if NOT staff goto normal_user$ if staff=0 goto normal_user And of course, you can "expand" the NAND/NEOR/NOR functions with the NOT: if a NAND b goto label$ if NOT (a and b) goto label JNotice that in this case, you must put parentheses around the "a and b" N Lequation, since the math in Metal is strictly left-to-right. This is done P Nto force Metal to evaluate the "a and b" expression before continuing on with the NOT function. NOT can be thought of as an logical "inverser": 1 - x 1 - 0 = 1 1 - 1 = 0 See also: AND, B.AND, B.EOR, B.OR, EOR, NAND, NEOR, NOR, OR O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== print "is now dead."illPartner,KillAlly,Kill Metal Commands : Section "O" Page Type: flow control command value Goto/Gosub/Push label1 label2 {,etc}} ON x Goto gold,jewels,weapons,armor,monster,trap* ON x Gosub EditUser1,EditUser2,EditUser3! ON x Push PressAkey,PressReturn MThe ON command is used in conjunction with the Goto, Gosub, or Push commands B to change where the program is at or where it is going to be at. HBetween each label , there must be a comma (",") - there may be spaces M Kbefore and after the comma, but it must be there! Any number of labels Mmay be used in the ON command, from one to 255 (A practical limit is about a J dozen, since Metal has a problem with lines longer than 255 characters). HWhat the ON command does is take the value of value and uses it as an P N"index" into the list of labels following the Goto, Gosub, or Push command. P NDepending on what value is equal to, ON will use the first, the second, the P Nthird, etc, label in the list, and then use whatever you told it to do - Goto L Jthat label, Gosub to that label and return after the list of labels, or ' Push the label onto the Return stack. KIf the ON command cannot get the label "number" that you asked it to - for P Nexample, you wanted the 5th label, but only 4 were listed, or you asked for a M Klabel number less than 1 (0, for example) - it will do nothing , skipping over the entire block of code. The following examples using the Goto syntax is shown: 1: X is equal to 2 ON x Goto FindHead,FindArm,FindLeg,FindKidney Here the FindArm label is used, since it is the 2nd label in the list. 2: X is equal to 7 ON x Goto FindHead,FindArm,FindLeg,FindKidney Here, the ON-Goto command does nothing , because there is simply ( no 7th label number - there is only 4. 3: X is equal to 0 ON x Goto FindHead,FindArm,FindLeg,FindKidney Again, nothing happens, because there is, of course, no "0th label". And now some examples using the Gosub syntax: 4: X is equal to 3 ON x Gosub KillEnemy,KillPartner,KillAlly,KillSelf print "is now dead." Here, the KillAlly routine is called, and it returns to the Print command. 5: X is equal to 20 ON x Gosub KillEnemy,KillPartner,KillAlly,KillSelf print "is now dead." Remember, there is no 20th label, so none of the listed routines D Bare called - all you will see is the Print "is now dead." routine F Dworking. (who's dead? Nobody - none of the KillSomeone routines are & called, so nothing really happened). 6: X is equal to 0 ON x Gosub KillEnemy,KillPartner,KillAlly,KillSelf print "is now dead." Again, same as example 5 - nothing happens, but "is now dead." ' shows up, totally confusing the user. GMany programming languages support the ON-Goto and ON-Gosub syntaxes - G EAppleSoft being one example. However, Metal has the extension to the K I"standard" in that is allows you to use the Push command. While the Push O Msyntax is of limited use, it was placed in the program to allow for possible usage by extreme programmers. See also: FOR, IF, GOSUB, GOTO, LONG IF, NEXT, THEN, TRAP, UNTIL, WHILE ONLINE$ Type: system value result$ =ONLINE$( slot drive vol$=ONLINE$(7,1) ram5$=ONLINE(3,2)% print "Volume name is "ONLINE$(s,d) LThe ONLINE$ command simply returns the volume name of the passed slot and O drive number. Slot may be from 1 to 7, and drive may be either 1 or 2. P NIf there is no device connected, an error occurs while reading the device, or I the device has no disk in the drive, ONLINE$ will return a null string. IONLINE$ always returns a null string (no device online, generally), or a N Lstring consisting of 2 to 16 characters. The first character of this string M will always be a slash ("/"), followed by the name of the volume or disk. MFor example, say you have a hard drive connected to slot 7 of your computer. L JYou only have one partition on this device, so there is only a drive 1 on ! slot 7 - drive 2 doesn't exist: print ONLINE$(7,1) returns /HD1: print ONLINE$(7,2) returns a null string This example, of course, assumes that you have named the hard drive "HD1". LSee also: CREATE, DELETE, DOSERR, FCOPY, FILEINFO$, ONLINE$, OPEN, PREFIX$, RENAME OPEN Type: command OPEN # filedevice filename$ OPEN #1,"users" OPEN #msgs,f$ MThe OPEN command is used to "open" an existing file and prepare it for input . (bload, input) and/or output (bsave, print). KWhat this means that you are basically readying a file for use - reading a I list of names, or writing a random access accounting file, for example. JOnce a file has been OPEN'd on a given filedevice , you then refer to it O Musing that filedevice . For example, let's say you OPEN the file "problems" onto file device #2: OPEN #2,"problems" LAt this point, Metal tries to open the file "problems" into device number 2 K I(remember, devices 1 through 4 are "file" devices used for OPEN and it's O Milk). If all goes well, the file is readied for use, setting several known things up: o the Filemark is initialized to zero (the first byte of the file).M o Doserr will contain a zero (no problems with the last command). KIf all does go well, the Doserr system value will contain the ProDOS Q Oerror number that occurred (most common results: Bad Buffer Address [device is K Ialready in use], File Not Found [doesn't exist], File Already Open [open 9 somewhere else or else you tried to re-OPEN it again]). JOnce the file is open, you can then access data inside of it, or put more N Ldata into it. For example, let's open our file "problems" and put data into OPEN #1,"problems"+ print #1,"This is the example." LIn this example, the very first part of the file (the first "line") will be C the string "This is the example" (without the quotes, of course). MDon't forget, after you have OPEN'd a file, you must Close it off in order L Jfor whatever output you did to it last to be saved, and for Metal to know O Mthat you are done with the file. If you do not, Metal will blindly leave the M Kfile open and in use, and later OPEN's on the same file channel will crash E the system with a Syserr of type #80 - File Channel Already In Use. MNote: Metal does not Create a missing file when you try to OPEN it. In order F Dto guarantee that the file will exist when you OPEN it, you must do something along this line: Create filename$ {,filetype,auxtype}- OPEN # filedevice filename$ NSee also: APPEND, BLOAD, BSAVE, CLOSE, CREATE, DELETE, DEVICE, DOSERR, FCOPY, F DFILEAUXTYPE, FILEINFO$, FILEMARK, FILESIZE, FILETYPE, FLUSH, INPUT, B @ONLINE$, POSITION, PREFIX$, PRINT, RENAME, RECNUM, RUN, RUNSUB, TCOPY Type: logic operand result operand1 OR operand2 z=x OR y if wounded OR sick goto doctor NThe OR command word is used to check the preceding ( operand1 ) and following 7 operand2 ) values and return either a 0 or 1 value. KOR will return a 1 value if either operand1 or operand2 are non-zero O Mvalues. It returns a zero value only if both operand1 and operand2 are both zero. OR can be thought of as an logical "adder": 0 + 0 = 0 0 + 1 = 1 1 + 0 = 16 1 + 1 = 1 (anything over 1 is considered a 1) MNote that the actual values of operand1 and operand2 don't really affect P Nthe outcome of the OR command - it just cares if the values are either zero non-zero - non-zero values are treated as a "1" value. See also: AND, B.AND, B.EOR, B.OR, EOR, NAND, NEOR, NOR, NOT O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== PRINT TAB command up! char$ -- doing so will "lock" Metal Commands : Section "P" Page PADDLE Type: math function result =PADDLE( index x=PADDLE(0) y=PADDLE(1)+ if PADDLE(0)>200 print "Sysop not around" NThe PADDLE function is used to simply read the connected paddles or joystick. M KSince the Apple joystick is nothing more than two paddles working together O M(one for the left-right or X axis, and the other for the up-down or Y axis), ! the joystick has immense range. MTo read the left-right or X axis of the joystick, you need to use PADDLE(0). + For the up-down or Y axis, use PADDLE(1). NThe PADDLE command is of limited use, but it can be used in different ways to R Pallow the sysop to dynamically interact with the user without having to press a key on the keyboard. KSee also: ABS, ASC, BITVAL, HEXVAL, INSTRING, LEN, MEMAREA, MEMSIZE, PEEK, C APEEKADDR, PEEKBYTE, PEEKWORD, RANDOM, ROTL, ROTR, SIGN, SYSINFO, PEEK Type: math function result =PEEK( address za=PEEK(hl)* if PEEK(memarea(1)+3)=100 goto EdgeOfMap MThe PEEK command is used to "look at" a byte of memory. It is very simple to P Nuse, and functions the same as the BASIC command Peek. However, Metal imposes , a few limitations on how you may use PEEK: You may not PEEK at anything above $8000 hex or 32768 decimal. This was G Edone to prevent you from accessing the Apple's I/O page and possibly crashing the system.G You may not PEEK at anything from $100 to $1FFF hex or 256 to 8191 K Idecimal. This was done to prevent you from accessing the stack, vectors, video screen, etc.O Mo If you try to PEEK at a memory location from $2000 to $7FFF hex or 8192 to E 32767 decimal, that location must have been previously Allocated. JGenerally, you will be PEEKing at a zero page location (0 to 255 decimal, K I$000 to $0FF hex) or off of some reference to an Allocated memory area - Memarea(x), Byte, Bit, etc. JPEEK always returns a value from 0 to 255; thus it is considered a byte Kpeek of memory. The command PEEKBYTE and PEEK are one and the same and are 2 translated by the compiler into the same opcode. MSee also: ABS, ASC, BITVAL, HEXVAL, INSTRING, LEN, MEMAREA, MEMSIZE, PADDLE, C APEEKADDR, PEEKBYTE, PEEKWORD, RANDOM, ROTL, ROTR, SIGN, SYSINFO, PEEKADDR Type: math function result =PEEKADDR( address za=PEEKADDR(hl), if PEEKADDR(memarea(3)+12)<0 goto Negative LThe PEEKADDR command is used to "look at" three bytes of memory. It is very I Gsimple to use, and functions the same, as the command Peek. Like Peek, 8 PEEKADDR imposes the same rules on how you may use it. NPEEKADDR returns a 3-byte value ranging from -8meg to +8meg - this means that P Nit looks at the data at address , the data at address +1, the data at address JLike the Addr command, PEEKADDR will return the full 24-bit integer value that Metal can use. MSee also: ABS, ASC, BITVAL, HEXVAL, INSTRING, LEN, MEMAREA, MEMSIZE, PADDLE, B PEEK, PEEKBYTE, PEEKWORD, RANDOM, ROTL, ROTR, SIGN, SYSINFO, VAL PEEKBYTE Type: math function result =PEEKBYTE( address za=PEEKBYTE(hl)+ if PEEKBYTE(memarea(2))=21 goto Blackjack KPEEKBYTE is the same as PEEK - you should refer to PEEK for information on this command. MSee also: ABS, ASC, BITVAL, HEXVAL, INSTRING, LEN, MEMAREA, MEMSIZE, PADDLE, B PEEK, PEEKADDR, PEEKWORD, RANDOM, ROTL, ROTR, SIGN, SYSINFO, VAL PEEKWORD Type: math function result =PEEKWORD( address za=PEEKWORD(hl)+ if PEEKWORD(memarea(9))>1000 goto TooMuch JThe PEEKWORD command is used to "look at" two bytes of memory. It is very I Gsimple to use, and functions the same, as the command Peek. Like Peek, 8 PEEKWORD imposes the same rules on how you may use it. MPEEKWORD returns a 2-byte value ranging from 0 to 65535 - this means that it ? looks at the data at address the data at address MSee also: ABS, ASC, BITVAL, HEXVAL, INSTRING, LEN, MEMAREA, MEMSIZE, PADDLE, B PEEK, PEEKADDR, PEEKBYTE, RANDOM, ROTL, ROTR, SIGN, SYSINFO, VAL PERCENTAGE Type: math function result =PERCENTAGE( index total x=PERCENTAGE(filemark(1),filesize(1))( print "I am "PERCENTAGE(ix,tl)"% done" KThe PERCENTAGE command is a built-in function that can be used in place of L Jthe command "calculate a percentage" routine. The math formula for such a routine is as follows: result index * 100 / total PERCENTAGE has three advantages over doing the routine yourself: 1) It's smaller. 2) It's faster.L 3) It handles values that would cause your routine to "go wild" correctly. MThe third advantage is the most important: Metal can only handle 23-bit math N L(the 24th bit is the pos/neg sign), so if you multiply a number larger than L J83,886 by 100, Metal will get confused and think you want to do something O Mwith the sign bit. The PERCENTAGE command will check for that condition, and O if it exists, will "auto-range" the values given so that it can work on them. See also: DAYNUM, MAKEWORKFILE, QUIT, RANDOM, SMF command, SWAPVAR PLAYTONE Type: command PLAYTONE ( duration pitch toneadd PLAYTONE (50,100) PLAYTONE (83,j,-1) KPLAYTONE will generate either a single tone or a sliding tone on the local M Kend (your computer). It does send out any special control codes over the modem. GThe PLAYTONE routine is a very simple one, and is not really suited to I Ggenerating quality music - it doesn't take advantage of the GS's sound F capabilities, for example - it uses the "standard" Apple II speaker. MThe PLAYTONE parameters are broken into two parts - the duration (how long L Jto play the tone), and the pitch . The smaller the value of pitch , the K Ihigher the sound of the tone - and the shorter it plays. Conversely, the O Mlarger the value of pitch , the lower the sound of the tone, and the longer it plays. MThe duration is how many times the routine will repeat the pitch value - N Lthus is you specify a duration of 60, then the PLAYTONE routine will play M Kthe pitch 60 times - you will not notice it doing so, as it comes out as one continuous tone. NThe optional toneadd value is added to the pitch each time it is played - K Ithus if you give a value of -1 for toneadd , then each time through the " duration , the pitch will rise. For example, if you give the following: PLAYTONE (60,100,-1) NThe first time the tone is played, it is played at a pitch of 100. The next O Mtime, it is played at 99, then 98, etc, so the tone will appear to "rise" up the scale. NThe limit of the pitch value is 0 to 2047. If the toneadd value causes it P Nto go past the 2047 limit, it wraps around to 0; if it goes below 0, it wraps around to 2047. See also: QUIT POKE Type: command POKE address value POKE hl,za POKE memarea(8)+2,9 NThe POKE command is the inverse of the PEEK command - instead of looking at a J Hbyte of memory, you change a byte of memory. It is simple to use, and M Kfunctions the same as the BASIC command Poke. However, Metal imposes a few & limitations on how you may use POKE: You may not POKE anything above $8000 hex or 32768 decimal. This was done K Ito prevent you from accessing the Apple's I/O page and possibly crashing the system.K You may not POKE anything from $000 to $1FFF hex or 0 to 8191 decimal. H FThis was done to prevent you from accessing the stack, vectors, video screen, etc.L Jo If you try to POKE a memory location from $2000 to $7FFF hex or 8192 to E 32767 decimal, that location must have been previously Allocated. IGenerally, you will be POKEing a reference to an Allocated memory area - Memarea(x), Byte, Bit, etc. LPOKE always operates on a single byte of memory; thus the value parameter P Nis treated as a value ranging from 0 to 255. Anything above 255 (or less than > 0) is handled as if it was given a B.AND 255 prior to usage. MThe command POKEBYTE and POKE are one and the same and are translated by the compiler into the same opcode. GSee also: ADDR, ALLOCATE, BIT, BLOAD, BSAVE, BYTE, DEALLOCATE, MCLEAR, ? =MCOPY, MEMAREA, MEMSIZE, MEMSTRING$, NIBBLE, PEEK, PEEKADDR, 8 PEEKBYTE, PEEKWORD, POKEADDR, POKEBYTE, POKEWORD, WORD POKEADDR Type: command POKEADDR address value POKEADDR hl,za POKEADDR memarea(12),men IThe POKEADDR command is used to change three bytes of memory. It is very I Gsimple to use, and functions the same, as the command Poke. Like Poke, 8 POKEADDR imposes the same rules on how you may use it. MPOKEADDR uses a 3-byte value ranging from -8meg to +8meg - this means that O Mit changes the data at address , the data at address +1, the data at address NLike the Addr command, POKEADDR can handle the full 24-bit integer value that Metal can use. GSee also: ADDR, ALLOCATE, BIT, BLOAD, BSAVE, BYTE, DEALLOCATE, MCLEAR, ? =MCOPY, MEMAREA, MEMSIZE, MEMSTRING$, NIBBLE, PEEK, PEEKADDR, 4 PEEKBYTE, PEEKWORD, POKE, POKEBYTE, POKEWORD, WORD POKEBYTE Type: command POKEBYTE address value POKEBYTE hl,za POKEBYTE memarea(8)+2,9 KPOKEBYTE is the same as POKE - you should refer to POKE for information on this command. GSee also: ADDR, ALLOCATE, BIT, BLOAD, BSAVE, BYTE, DEALLOCATE, MCLEAR, ? =MCOPY, MEMAREA, MEMSIZE, MEMSTRING$, NIBBLE, PEEK, PEEKADDR, 4 PEEKBYTE, PEEKWORD, POKE, POKEADDR, POKEWORD, WORD POKEWORD Type: math function POKEWORD address value POKEWORD hl,za POKEWORD memarea(83)+12,a*x NThe POKEWORD command is used to change two bytes of memory. It is very simple K Ito use, and functions the same, as the command Peek. Like Peek, POKEWORD / imposes the same rules on how you may use it. LPOKEWORD uses a 2-byte value ranging from 0 to 65535 - this means that it > changes the data at address the data at address GSee also: ADDR, ALLOCATE, BIT, BLOAD, BSAVE, BYTE, DEALLOCATE, MCLEAR, ? =MCOPY, MEMAREA, MEMSIZE, MEMSTRING$, NIBBLE, PEEK, PEEKADDR, 4 PEEKBYTE, PEEKWORD, POKE, POKEADDR, POKEBYTE, WORD Type: complex flow command POP { extender POP IF POP LONG IF POP FOR POP NEXT POP RETURN POP DO POP WHILE JThe POP command is normally used to remove the last GOSUB from the stack. O MHowever, it has six other optional extenders that all you to remove almost . anything from the internal "looping stacks": This is the default, and removes the current GOSUB.: POP RETURN This is an optional syntax for the default.M KPOP IF Removes the current IF/LONG IF from the IF-THEN stack. Useful only in a Long-If condition.* POP LONG IF Optional syntax for POP IF.1 POP DO Removes the current Do-Until loop.7 POP WHILE Removes the current While-EndWhile loop.1 POP FOR Removes the current For-Next loop.+ POP NEXT Optional syntax for POP FOR. NNote that if a POP tries to remove the given "loop" and there are none active > (say, no For-Next loops going on), then nothing will happen. See also: CLEAR, DO, END, FOR, GOSUB, IF, LONG IF, NEXT, RETURN, UNTIL, WHILE POSITION Type: command POSITION {# device recnum reclen byteoffset POSITION #1,r,64 POSITION #1,x,64,p*4 POSITION #1,9 POSITION a*10,8,xq+1 The POSITION command is used to change the Filemark of a currently open file. PFunctionally, the POSITION command is nothing more than a straight-forward math H Fexpression. It can be though of (and is directly equivalent) as the following: Filemark( device recnum reclen byteoffset LSimple, yes, but let's talk about the format for the syntax of POSITION and what the parameters mean. KThe recnum is the record number that you wish to access. Generally, this : will be some variable value, say, "A" or "USER*10", etc. LThe reclen is the record length of each record. Since each record must be F Dthe same length (say, 1024 bytes per each record, or 64 bytes, etc) M Kthroughout the file, it is easy to figure out where the record starts at - O Mtake the given record number ( recnum ) and multiply it by the record length reclen LThe optional byteoffset is the number of bytes into the record that you O Mwish to skip over to. If you don't use this parameter, then it defaults into O Mzero - the first byte of the record. But if you want to skip, say, the first = 10 bytes of the record, you supply a "10" for byteoffset FFinally, there is a little-used but supported option. If you omit the O reclen and the byteoffset values, then POSITION will use the open file's O MAuxiliary File Type as the record length (see the Create and Recnum commands - for more information about Aux File Types). ILike the Filemark command, if you attempt to go past the end of the file N L(exceed the length of the file), then Metal will automatically "extend" the O Msize of the file out. Note that ProDOS-8 does do this for you, this is a function of Metal. FSee also: APPEND, BLOAD, BSAVE, CREATE, CLOSE, DEVICE, DOSERR, FCOPY, F DFILEAUXTYPE, FILEMARK, FILESIZE, FLUSH, INPUT, OPEN, PRINT, RECNUM, TCOPY PREFIX$ Type: system variable PREFIX$= string$ result$ =PREFIX${( pathnum PREFIX$=new$ cur$=PREFIX$ p1$=PREFIX$(1) ram5$=PREFIX$(9) MThe PREFIX$ is used to read the current default ProDOS prefix or to set up a new one. KUnlike Create, which will create missing sub-directories, PREFIX$ will not O build a "path" to a prefix if one or more of the sub-directories are missing. MTo change the current default prefix to a new one, you simply equate PREFIX$ to a given string. ITo read the current default prefix, you just read PREFIX$ like any other F variable. In this regard, PREFIX$ is nothing more than a variable. KIf you wish to check where one of the ten defined pathnumbers (set through I Gthe Metal.Config file), you use the optional ( pathnum ) syntax, where + pathnum is a value ranging from 0 to 9. MRemember, setting the PREFIX$ allows you to use the pathnumbers as the first N Lcharacter of the string, but reading PREFIX$ returns the physical or real O Mpathname - "expanded" out, so to speak. For example, let's say you have path A number 7 set to "/HD1/BBS/MY.FILES/" and you did the following: PREFIX$="7/" a$=PREFIX$ The value of A$ will be "/HD1/BBS/MY.FILES/", not "7/" as you would expect. KSee also: CREATE, DELETE, DOSERR, FCOPY, FILEAUXTYPE, FILEINFO$, FILEMARK, 6 FILESIZE, FILETYPE, OPEN, RENAME, RUN, RUNSUB, TCOPY PRINT Type: complex command ;PRINT {# device {,}} {AT ( )} { string$ expression numerical expression } {" literal text "} { literal number variable } {TO{,} variable2 } {CR{( times }} @ {TAB( to_pos char$ })} {REPEAT$( string$ times )} {,} {;} PRINT "You'll be using this on a lot!"% PRINT At(p1*8,p2+2) Repeat$("*",z); PRINT #1,usr$(0) To usr$(15) MIf you thought Input was a nightmare, now consider PRINT - Input only had 10 % optional parameter; PRINT has LThe PRINT command is by and far the most heavily used command in Metal - in M order to get something out to the screen, you must use the PRINT command. LAs you can see, PRINT allows you to print anything and everything - it also G allows you a fair amount of control of it is output, and where. NOne at a time, here are the optional parameters. Note that for the most part, D the actual order of the parameters in the program is not a factor. Parameter Does --------- ---- device By using this, you are telling the PRINT command to output : 8the text some place other than the default Device value : 8(normally, this is zero, but you can change this if you > <- it is suggested that you do so, just to make your program code clearer to others. MAT( ) The AT optional changes where the following text output is 6 4to take place at on the screen. If the Metal.Config > <"AutoPos" is turned on, then Print will send out the needed < :control codes over the modem to have the terminal program > > ). Any > "Y" return run "1/xfers" MThe commands underlined are the ones you should notice - after the main.help / file is displayed, it returns to MainCommand. JThe following is the same code, but using GOTO MainCommand instead of the returns: MainCommand. print "Main Level, what is your choice? "; MainComm1 get mode(1) a$ if a$="?" goto MainHelp if a$="X" goto EnterXfers" {some more if-gotos like this} goto MainComm1 MainHelp1( tcopy "main.help": goto MainCommand EnterXfers- input mode("U") "Enter the transfers?" i$! if i$<>"Y" goto MainCommand run "1/xfers" JNow, if you notice a few things, you'll realize something: if you use the P NPUSH MainCommand example, you only have to type the label MainCommand twice - P Nonce when you define it, the second where to PUSH it. Then you just Return to L Jit. However, the Goto MainCommand has to be typed each and every time you M Kneed to go back - increasing the chance for errors and wasting good typing time. H(Plus you can then use the routines such as MainHelp1 and EnterXfers as , sub-routines from other sections of code). GSee also: FOR, IF, GOSUB, GOTO, LONG IF, ON, NEXT, RETURN, THEN, TRAP, UNTIL, WHILE PUSHVAR Type: command PUSHVAR variable variable2 variable3 ...}} PUSHVAR hi,ho,it$,off,2,work,we,go KThe PUSHVAR command places variable values on the stack (note the "2"?), O Mnot the actual variable. This means you can place expressions on the stack and then retrieve them back. HLet's talk about how the stack works. First off, there are actually two O MPUSH/PULLVAR stacks - one for numbers, one for strings. The operate the same 1 way, but are totally independent of each other. JWhen a value is pushed onto the stack, it becomes the "top" value, or the M Knext one off. Sort of like placing a plate on top of a stack of them - you P Nnormally take one from the top rather than trying to slide one out from under the rest of them. KLet's visualize how this stack is set up, so you can get a better feel for 6 it. Pushing the following numbers onto the stack.... PUSHVAR 1991,1900,501,386,65816 65816 1900 1991 Then we do so more stuff, and push a little more onto the stack: PUSHVAR age,weight value of "weight") value of "age" 65816 1900 1991 INotice how the stack "moved" down? Now, if we pulled a variable off this K stack, we'd get back the value of weight, then age, then 65816, etc, etc. See also: PULLVAR O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== Metal Commands : Section "A" Metal Commands : Section "Q" Page QUIT Type: command QUIT {TO filename$ QUIT QUIT TO f$ QUIT TO "/hd1/proterm" MThe QUIT command can be used to exit Metal back to the program selector that . launched it, or exit to another SYStem file. KIn the first syntax, QUIT without the optional TO filename$ , Metal exits O Mback to the ProDOS "Bye" or "Quit" command. This means that Metal returns to M Kwhatever program launched it - Wings, the Finder, Zlaunch, Super Selector, O Metc. This is the same thing that is done when you press open-apple-control-Q from the local keyboard. MThe second syntax, QUIT with the optional TO filename$ , Metal will attempt L Jto launch and run the given system file. If it cannot find it, Metal just exits back normally. HThe only effect this command has on the remote user or the modem is the = shutting it down, disconnecting the user, if one is online. See also: PLAYTONE, PREFIX$ !"#$%&'() O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== FILETYPE, OPEN, PREFIX$, RENAME, RUNSUB, TCOPYUXTYPE, Metal Commands : Section "R" Page RANDOM Type: math function result =RANDOM( value x=RANDOM(80) if RANDOM(100)<50 goto YouLost LThe RANDOM command returns a random number based on the passed value . The P Nnumber returned will always be in the range of zero (0) to value -1. Thus if A you ask RANDOM(80), you will get a number ranging from 0 to 79. KRANDOM is mostly used in online games and to "clever up" your program with 4 random messages sprinkled throughout. For example: x=RANDOM(5)( if x=0 print "Have a nice day!"$ if x=1 print "Break a leg!"+ if x=2 print "Get outta my sight!"- if x=3 print "Don't drive too fast!": if x=4 print "Take a long walk off a short pier!" KSee also: ABS, ASC, BITVAL, HEXVAL, INSTRING, LEN, MEMAREA, MEMSIZE, PEEK, C APEEKADDR, PEEKBYTE, PEEKWORD, PADDLE, ROTL, ROTR, SIGN, SYSINFO, RECNUM Type: system variable RECNUM( device record record =RECNUM( device RECNUM(2)=user crec=RECNUM(4) HThe RECNUM (RECord NUMber) is very similar to the Position and Filemark M Kcommands. Like Filemark, it allows you to read whereabouts in the file you I are at, and like Position, it lets you move to a certain record number. LRECNUM is normally used with reading directory files (usually within a file O Mtransfer program, such as FV Xfer or Moses). However, it can also be used in C Aplace of the Filemark and Position commands when being used with non-directory files. HSince RECNUM is a system variable, this means you can read what current H record number you are at, and set which record number you wish to use. LSince, under ProDOS-8, there are two "file structures" (directory files and ? non-directory files), RECNUM handles both slightly different. KThe most common use of RECNUM, as mentioned, is using it to position to an J Hentry number (the record) in a directory file. This is really simple to K Iaccomplish - equate RECNUM( device ) to the entry (starting at the first M entry - 1 - and going to whatever), and Metal will find the entry you want. KFor example, the following code is similar to what Moses uses to display a directory listing: open #1,"/HD1/XFERS/VOLUME.5" r=1 Loop RECNUM(1)=r input #1,a$ if a$="" goto NoMoreFiles print a$ r=r+1 goto Loop NoMoreFiles close #1 return MSimple, eh? Very simple, yes. But why bother with that routine when a simple N Linput #1,a$ without the RECNUM command would do the exact same job? Well, % let's modify the code a little bit: open #1,"/HD1/XFERS/VOLUME.5" r=1 Loop RECNUM(1)=r input #1,a$ if a$="" goto NoMoreFiles print a$1 if sysinfo(1)=13 clear input:r=r+10:else r=r+1 goto Loop NoMoreFiles close #1 return ANote the extra line with the SYSINFO(1) command (which reads the O Mkeyboard/modem buffer). If the user presses the Return key, then the routine Q Owill skip forward 10 lines instead of just to the next one - thus the user can 0 "jump" through a directory quickly and easily. NIn this regard, writing a routine to display a scrolling "list" of files in a N transfer volume would depend on nothing more than a little loop of RECNUM's. Now, the other part of RECNUM: using it with non-directory (standard) files. KEvery time Metal opens a file, it remembers the auxiliary file type of the , file. Generally, this only has a few uses: 1) Binary files: where to load and run the file at.H 2) AppleWorks files: the "case" of the filename (not really critical).= 3) Text files: size of each record for random-access files. MThe one that we care about is #3 - size of each record. When you read or set N LRECNUM when using a standard file, Metal will use the auxiliary filetype of # that file as the record length NFor example, say you open a file that has a auxiliary file type of 512 - this O Mmeans that the record length of the file is 512 bytes per each record. Thus, I the following two lines will accomplish the same thing for this file RECNUM(1)=z POSITION #1,z,512 However, a true "equivalent" to setting RECNUM is as follows: RECNUM(1)=z POSITION #1,z,FILEAUXTYPE(1) MNow, when you read RECNUM for a standard file, it does the reverse: it takes O Mthe current Filemark value and divides it by the auxiliary file type, giving ! you which record number you at. So, reading RECNUM can be thought of as smaller version of: z=RECNUM(1) z=FILEMARK(1)/FILEAUXTYPE(1) NThere are two very critical differences (other than the obvious) in the way 3 RECNUM handles directory and non-directory files: Directories: o RECNUM does not allow you to access record number zero. IE: RECNUM(1)=0 is a no-no.L o RECNUM will not extend the size of a directory file if you set RECNUM J Hpast the total possible size of the file. It will simple advance to the end and stop. Non-directories:; o RECNUM does allow you to access record number zero.O o RECNUM does extend the size of the file if you set RECNUM past the end of the file. FSee also: APPEND, BLOAD, BSAVE, CREATE, CLOSE, DEVICE, DOSERR, FCOPY, A ?FILEAUXTYPE, FILEMARK, FILESIZE, FLUSH, INPUT, OPEN, POSITION, PRINT, TCOPY RENAME Type: command RENAME filename$ newname$ RENAME filename$ TO newname$ RENAME "2/list","2/list.copy" RENAME f$ to z$ LThe RENAME command does just that - it renames the given filename$ to the O Mgiven newname$ . This is simple and easy to do, but ProDOS (not Metal) puts some limitations on this: 1) There must not be a file using newname$ already on the disk.M K2) The filename$ and newname$ files must be in the same directory, and L Jyou must give the same prefix to both - thus you must use RENAME "2/file" 3 TO "2/renamed", not RENAME "2/file" TO "renamed".P N3) ProDOS will not allow you to try and "move" the file from one directory to the other.O M4) ProDOS may, in certain cases , allow you to rename disk volumes. Be wary of this. MSee also: DELETE, DOSERR, FCOPY, FILEAUXTYPE, FILEINFO$, FILESIZE, FILETYPE, , ONLINE$, OPEN, PREFIX$, RUN, RUNSUB, TCOPY REPEAT$ Type: string function result$ =REPEAT$( string$ times print REPEAT$( string$ times OThe REPEAT$ command is used to save you typing time and allow more flexibility L Jin your code. All it does is take the given string$ , and put it times into the result$ . Thus, if you do the following: a$=REPEAT$("TCQ",5) Then a$ will be equal to "TCQTCQTCQTCQTCQ" (minus the quotes of course). HREPEAT$ will complain with a String Overflow Error if you try to make a G result$ that is larger than 255 characters (this is real easy to accomplish). NThe Print version of REPEAT$ doesn't have this problem, as it doesn't care if = the result is 1 or 1000 characters - it just prints it out. LSee also: BITSTR$, CHR$, CNGCASE$, FILEINFO$, HEXSTR$, LEFT$, MID$, RIGHT$, STR$ RETURN Type: flow control RETURN IThe RETURN command is simple to use - by simply executing it, Metal will . return to where the last Gosub was executed. Examples: Gosub GetKey GetKey get a$ RETURN ----------- trap syserr gosub SystemErr SystemErr print "Whoops!" RETURN ----------- on x Gosub Rout1,Rout2,Rout3,Rout4 print "Returns to here" Rout1 RETURN ----------- LSee also: FOR, IF, GOSUB, GOTO, LONG IF, ON, PUSH, NEXT, THEN, TRAP, UNTIL, WHILE, Local Variables RIGHT$ Type: string function result$ =RIGHT$( string$ length a$=RIGHT$(a$,9)" print RIGHT$(" "+str$(x),5); LRIGHT$ is part of the Left/Right/Mid string "package" of commands. Like the N LLeft$ and Mid$ commands, RIGHT$ takes the given string$ value and returns 8 part of it. What part? Why, the right-hand side of it. Examples: a$=RIGHT$("Wilson Wares",5) a$ will be equal to Wares a$=RIGHT$(name$,len(name$),-1)K ISay that name$ is "Apple IIGS" (which is 10 characters long). a$ will be M Kequal to "pple IIGS" (since we wanted everything but the first character - # the length of the name$ minus 1). HIf you use a value of zero for length , then RIGHT$ will return a null string. MSee also: BITSTR$, CHR$, CNGCASE$, FILEINFO$, HEXSTR$, LEFT$, MID$, REPEAT$, STR$ ROTL Type: math function result =ROTL( value x=ROTL(z) MROTL (ROTate Left) is a bit-wise function - it treats the given value as a J H24-bit "string" and shifts it down, bringing the left-most bit over and around to the right. Visually, it looks like this: Before: ABCDEFGHIJKLMNOPQRSTUVWX, After: BCDEFGHIJKLMNOPQRSTUVWXA KWhat use it this? Not much, but it has it's place in certain applications. P N(actually, this command was requested by a user but was never taken advantage of). See also: B.AND, B.EOR, B.OR, BITVAL, ROTR, SYSINFO ROTR Type: math function result =ROTR( value x=ROTR(z) NROTR (ROTate Right) is a bit-wise function - it treats the given value as a K I24-bit "string" and shifts it down, bringing the right-most bit over and around to the left. Visually, it looks like this: Before: ABCDEFGHIJKLMNOPQRSTUVWX, After: XABCDEFGHIJKLMNOPQRSTUVW See also: B.AND, B.EOR, B.OR, BITVAL, ROTL, SYSINFO Type: program flow command RUN filename$ global$ RUN "1/MAIN.LEVEL" RUN "1/CONQUEST","Fight" RUN i$,g$ LThe RUN command is the only way that you have to switch from one program to I Ganother. Actually, all the programs that your system will be using are M Kconsider a sub-set of each other (they all can run each other at any point L Jand time, without losing any variables), but it makes things cleaner (and H much less mind-boggling) to keep all the file transfers in the file transfer program, etc. KThe filename$ parameter is the source program to run. All Metal source M Kfiles end with the ".S" suffix, so a directory of your programs would look like this: IEBS STARTUP.S MAINT1.S XFERS.S MSG.BASE.S NET.MAINT.S NET.MAINT2 GLOBAL.WAR.S JIf this source file is missing, Metal will crash with an System Error - Unable to Run Module. LNormally, RUN is used to exit out of one program and enter into another one M at the beginning. This is accomplished by not using the global$ optional. JHowever, there are many times you don't wish to enter at the start of the O Mprogram - more than likely, you want to start somewhere else. A good example I Gof this is having your message base program enter into the user logoff O Mroutine in your main level program. This is accomplished by passing the name A of the label you wish to enter into via the global$ optional. IIn order for the global$ to work, Metal must be told that the label is O Mconsidered "global" or "available for other programs to enter into it". This A is done by placing "GLOBAL" after the label when you define it: NotAGlobal7 print "This label cannot be run by another program" Term0A globalC print "This label is global, and can be run by another program" MIf the given global$ label doesn't exist in the program to run, Metal will G crash (with a non-trappable ) System Error - Global Label Not Found. LWhen you RUN a program, Metal checks if the program needs to be "compiled". N LIt does this by checking if the "object code" file exists and if the source L Jfile has been modified. Metal also checks to see if the "object code" was O compiled under an older version of Metal - if so, it re-compiles the program. LOnce Metal get the "object code" file found and ready to be used, it clears M Kout certain things. Metal, on a RUN, remove all Traps and the Gosub/Return J Hstack. It leaves all Pushvar values on the stack, and all variable data intact. KSee also: CREATE, DELETE, DOSERR, FCOPY, FILEAUXTYPE, FILEINFO$, FILESIZE, 0 FILETYPE, OPEN, PREFIX$, RENAME, RUNSUB, TCOPY RUNSUB Type: program flow command RUNSUB filename$ global$ RUNSUB "1/R/GETKEY" RUNSUB "1/GAMEROUTS","Fight" RUNSUB rf$,rg$ MThe RUNSUB command is a combination of the Gosub and Run commands. It allows K Iyou to run a routine out of another program without having to constantly A reset the traps and worry about loosing the Gosub/Return stack. IIn all respects, RUNSUB works exactly like a RUN, but with the following exceptions: Mo RUNSUB stacks off the Traps and the Gosub/Return stack so that they may be recovered later.M Ko RUNSUB is exited by RUNRETURN, which returns to where the RUNSUB command was executed. KSee also: CREATE, DELETE, DOSERR, FCOPY, FILEAUXTYPE, FILEINFO$, FILESIZE, 8 FILETYPE, OPEN, PREFIX$, RENAME, RUN, RUNRETURN, TCOPY RUNRETURN Type: program flow command RUNRETURN LThe RUNRETURN command is used in conjunction with the RUNSUB command. It is L Jused to return from a RUNSUB, just like a Return is used to return from a Gosub. See also: RUNSUB +,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== Keyboard. Sysop SMF Routines, SMF_READ, SMF_REMOVE, S Metal Commands : Section "S" Page SIGN Type: math function result =SIGN( value x=SIGN(y-2) if SIGN(x)=1 goto IsPos LSIGN simply returns a number that is based upon the sign of the value . It % only returns three possible values: o if value is zero, then result is zero.A o if value is less than zero (negative), then result is -1.C o if value is greater than zero (positive), then result is 1. KSee also: ABS, ASC, BITVAL, HEXVAL, INSTRING, LEN, MEMAREA, MEMSIZE, PEEK, E CPEEKADDR, PEEKBYTE, PEEKWORD, PADDLE, RANDOM, ROTL, ROTR, SYSINFO, SMF_ALLOCATE Type: command( SMF_ALLOCATE( channel block size SMF_ALLOCATE(msg,bltn,x) KThe SMF_ALLOCATE command is used on a currently opened SMF (Single Message M KFormat, commonly called a Message File) to set aside or "allocate" a given . number of bytes (or characters) for a block. NIf the given block is already set aside (ie: the size of the block is not * zero), the SMF_ALLOCATE will do nothing. MOtherwise, SMF_ALLOCATE will try to locate a range of space in the file that K Iis size bytes long, and set up internal pointers to that space for the block NAfter the SMF_ALLOCATE command is finished, the SMF_ATRIB and SMF_USER values N Lfor that block are zero, and the current Filemark pointer for the channel specified is set to the start of the newly created block NNote that SMF_ALLOCATE does clear out any "old" data that may be in the O Mfile at this point - it is assumed that you wish to overwrite the older data with new data. GAlso note that each time SMF_ALLOCATE is used, it checks to see if the L block being passed is greater than the total number of blocks currently O Mbeing used by that SMF file; if so, it sets the given block as the highest block in use on the file. MSee also: SMF_ATRIB, SMF_CLOSE, SMF_CREATE, SMF_DELETE, SMF_FLUSH, SMF_INFO, A ?SMF_OPEN, SMF_READ, SMF_REMOVE, SMF_SIZE, SMF_USER, SMF_WRITE, Using SMF Routines SMF_ATRIB Type: system variable result =SMF_ATRIB( channel block SMF_ATRIB( channel block value x=SMF_ATRIB(msg,bltn) SMF_ATRIB(3,120)=85 KEach SMF Block has two program-usable fields: these are the Atrib and User fields of the block. LWhenever a SMF_ALLOCATE is done to create a new block, these fields are set to zero. LSetting SMF_ATRIB is just the same as setting any other numerical variable: O Mthe range limit is the full 24-bit integer limit Metal imposes; thus you can / set SMF_ATRIB to a value from -8meg to +8meg. Reading SMF_ATRIB is just the same as reading another numerical variable. LNOTE: Due to the way the SMF routines are coded inside of Metal, you cannot M Kuse more than one SMF_xxx routine in the same expression. For example, the 1 following code line will give a false result: SMF_ATRIB(3,100)=SMF_ATRIB(4,20) JYou will have to save the second SMF_ATRIB off into another variable as a "holder" in order to use it: x=SMF_ATRIB(4,20) SMF_ATRIB(3,100)=x FSee also: SMF_ALLOCATE, SMF_CLOSE, SMF_CREATE, SMF_DELETE, SMF_FLUSH, @ >SMF_INFO, SMF_OPEN, SMF_READ, SMF_REMOVE, SMF_SIZE, SMF_USER, SMF_WRITE, Using SMF Routines SMF_CLOSE Type: command SMF_CLOSE( channel SMF_CLOSE(msg) JThe SMF_CLOSE command is used to close the currently open SMF file on the O channel channel number. Doing so writes out any change SMF info and closes 1 the file, freeing the channel for future use. Each SMF_OPEN must be followed (somewhere) by a SMF_CLOSE command. FSee also: SMF_ALLOCATE, SMF_ATRIB, SMF_CREATE, SMF_DELETE, SMF_FLUSH, @ >SMF_INFO, SMF_OPEN, SMF_READ, SMF_REMOVE, SMF_SIZE, SMF_USER, SMF_WRITE, Using SMF Routines SMF_CREATE Type: command SMF_CREATE( filename$ max_blocks SMF_CREATE(brds$,256) SMF_CREATE("9/my.smf",max) LThe SMF_CREATE command is used to set up a new, blank SMF file. You pass it N Lthe filename$ of the file to create (or re-create), and the total maximum H number of blocks that you wish to have in the SMF file ( max_blocks MIf the filename$ already exists, then SMF_CREATE will delete that file and create a new one. NSMF_CREATE does open the new file into a file channel for you; you must = do that yourself using the SMF_OPEN command if you need to. ESee also: SMF_ALLOCATE, SMF_ATRIB, SMF_CLOSE, SMF_DELETE, SMF_FLUSH, @ >SMF_INFO, SMF_OPEN, SMF_READ, SMF_REMOVE, SMF_SIZE, SMF_USER, SMF_WRITE, Using SMF Routines SMF_DELETE Type: command SMF_DELETE( channel block SMF_DELETE(msg,bltn) SMF_DELETE(3,100) KThe SMF_DELETE command is used to remove the given block from use in the M KSMF file. It does this by marking the area of the file that the block is N Lusing as free (available for re-use via SMF_ALLOCATE); marking its entry in P Nthe SMF file as unused, and then bringing all the following SMF blocks down / by one (as if you tore out a page in a book). GAfter an SMF_DELETE, the highest block in use value of the SMF file is decreased by one. ESee also: SMF_ALLOCATE, SMF_ATRIB, SMF_CLOSE, SMF_CREATE, SMF_FLUSH, @ >SMF_INFO, SMF_OPEN, SMF_READ, SMF_REMOVE, SMF_SIZE, SMF_USER, SMF_WRITE, Using SMF Routines SMF_FLUSH Type: command SMF_FLUSH( channel SMF_FLUSH(msg) SMF_FLUSH(4) LThe SMF_FLUSH command acts the same as if you had closed the SMF file using O MSMF_CLOSE, but it leaves the file open. This command is useful if you expect P Nto leave the SMF file open for long periods and don't want to run the risk of < having the file corrupted if something happens to the BBS. FSee also: SMF_ALLOCATE, SMF_ATRIB, SMF_CLOSE, SMF_CREATE, SMF_DELETE, @ >SMF_INFO, SMF_OPEN, SMF_READ, SMF_REMOVE, SMF_SIZE, SMF_USER, SMF_WRITE, Using SMF Routines SMF_INFO Type: system value result =SMF_INFO( channel parm NThe SMF_INFO command is used to return certain information from the SMF file. D The parm value controls what is actually returned into result parm means/ ---- ---------------------------L Version of the SMF file, in hexword format. Divide this = ;number by 256 for the major version,; the remainder is the 7 5minor version. This will always be 256 (indicating a version of 1.0)K Maximum number of blocks that can be in use at any one = ;given time. This value is set when the SMF file is created 6 using the SMF_CREATE(filename$, maxblocks ) command.M Highest (or total) block in use in the SMF file. A value ; 9of zero indicates that there are no blocks in use in the file.O Total number of free blocks in the file available for use. > Print "You have "STR$(cash)" gold on hand."9 Right way-> Print "You have "cash" gold on hand." MSTR$ is normally used inside of a Right$, Left$, or Mid$ function to prepare K Isome visual output, usually for a countdown or to line the display up in , columns (making it "pretty" for the user). MIf you wish STR$ to return just a certain amount of characters, you can give N Lit the optional , command. This option will tell STR$ to "pad out" the O Mleft side of the string with zeros, and return only as much as it can. Thus, 6 the following two lines will display the same thing: print right$("000"+STR$(baq),4) print STR$(baq,4) MSee also: BITSTR$, CHR$, CNGCASE$, FILEINFO$, HEXSTR$, LEFT$, MID$, REPEAT$, RIGHT$, VAL SWAPVAR Type: command SWAPVAR var1 var2 SWAPVAR a,b SWAPVAR b$(x),b$(y) LSWAPVAR simply exchanges the values between var1 and var2 . In our first J Hexample, if "a" was equal to 5, and "b" was equal to 19, then after the / SWAPVAR, "a" would be 19, and "b" would be 5. See also: CLEAR, PULLVAR, PUSHVAR SYSCNTRL Type: system variable result =SYSCNTRL( number SYSCNTRL( number value x=SYSCNTRL(2) SYSCNTRL(1)=3 GSYSCNTRL (SYStem ConTRoL) is used to check and set certain operational G conditions under Metal. The value of number can range from 1 to 11. number means... buffering frequency- show/hide invisible files- case-shift GSOS filenames8 re-order modification/creation dates4 allow DIR files to have auxtypes -unused- -unused- -unused- -unused-0 perform Rot13 on data output1 cr character is actually this KSYSCNTRL(1) is used to control how often Metal goes to look for input from K Ithe user during text output. This directly affects how fast Metal will N Lrespond to control-S (pause) or the Abort$. The value of SYSCNTRL(1) ranges from 1 to 9. SYSCNTRL(1)=1: Metal will check input each and every character (100%)J SYSCNTRL(1)=2: Metal will check input every other character (50%)H SYSCNTRL(1)=3: Metal will check input every 4th character (25%)J SYSCNTRL(1)=4: Metal will check input every 8th character (12.5%)K SYSCNTRL(1)=5: Metal will check input every 16th character (6.25%)L SYSCNTRL(1)=6: Metal will check input every 32nd character (3.125%)K SYSCNTRL(1)=7: Metal will check input every 64th character (1.56%)K SYSCNTRL(1)=8: Metal will check input every 128th character (.78%)K SYSCNTRL(1)=9: Metal will check input every 256th character (.39%) MNote that Metal always checks input each time a carriage return is printed out. NThe default for SYSCNTRL(1) is 6 - 64th character. This means that Metal will 6 check, on the average, three times per printed line. GSetting SYSCNTRL(1) to a lower value will improve control-S and Abort$ 1 handling, but will degrade system output speed. HYou may re-define the default (or only) setting for SYSCNTRL(1) in your 3 Metal.Config file by using CHARBUFFREQ=< value CSYSCNTRL(2) controls the showing of "invisible" files when reading K Idirectories. Invisible files are those files that have their "invisible" M Kaccess bit turned on. This can only be done when the file is created under L Janother operating system other than Metal (for example, The Finder, which E uses invisible files to "hide" it's window/icon information files). NSYSCNTRL(2) defaults to 0, which means do show invisible files. Setting / SYSCNTRL(2) to 1 will show invisible files. KNote that you can always open and access invisible files, no matter what the setting of SYSCNTRL(2) is. NSYSCNTRL(3) controls whether or not Metal will perform a GSOS "case shift" on N Lthe filename when reading a directory. GSOS allows files to have lower-case P Nletters in the filename (even though they are stored as upper-case letters on H Fthe disk), and uses an area of the "file definition" to record if the 5 filename has lower case letters and which ones are. ISYSCNTRL(3) defaults to 0, which means do perform a case shift; it P Npresents all filenames back as upper case. Setting SYSCNTRL(3) to 1 will tell Metal to the case shift. NSYSCNTRL(2) and SYSCNTRL(3) have no other effect outside of reading directory K Ifiles. FileInfo$ will always report back on any file, using upper case filenames. LNormally, Metal will report back whatever the values of the file's creation O Mand modification dates are. However, file transfers tend to use the creation N Ldate of the file as the date uploaded, and the modification date as when it P Nwas originally created (weird, yes). Setting SYSCNTRL(4) to a value of 1 will H Ftell Metal to re-order the modification and creation date in a file's O Mdirectory listing FileInfo$ to what is correct - the creation date will M always be the oldest date, and the modification will always be more recent. IMetal normally forbids you to give auxtypes to Directory files. However, H Fthere may be a reason that you want to do this. In this case, you can O Moverride Metal's default by turning this off: setting SYSCNTRL(5) to a value . of 1 will let Metal give DIR files auxtypes. KSYSCNTRL(6) through SYSCNTRL(9) are undefined at the time of this writing, P Nand are being left open for future use. Usage of these options will not cause O Manything "bad" to happen, until Metal is changed to where it starts to use these values. JSYSCNTRL(10) lets you turn on and off the Rot13 option. Rot13 refers to a F Dcommon encryption format being used on InterNet and UseNet; all the P Ncharacters from A to Z and a to z are shifted over by 13, so that A becomes N L Jand N becomes A. Normally, this defaults to off (zero). Setting this to 1 J H(on) will tell Metal to perform a Rot13 on almost all text output. This includes PRINTing, TCOPY, etc. IThe value of SYSCNTRL(10) is forced to zero when any TRAP becomes active M K(thus if the user drops carrier or an error occurs, this is zeroed). It is * also zeroed on any INPUT or GET command. NThe Shell Command "ROT13" will also perform this action across an entire text file. LSYSCNTRL(11) provides a cheap and easy way to re-define the carriage return L Jcharacter that Metal uses. Why would you want to do this? Well, if you're M working on a program to convert between Apple and Unix, you could use this. KSYSCNTRL(11) always defaults to 13, and should be changed unless you O Mknow what you're doing - it affects all the input routines going to and from the disk. HSee also: ABORT$, FILEINFO$, GET, INPUT, OPEN, POSITION, PRINT, RECNUM, SYSINFO, Writing Externals SYSERR! Type: system value/buried token result =SYSERR& Trap SYSERR{= value link label last=SYSERR Trap SYSERR goto CrashIt NSYSERR (the last SYStem ERRor number) is used primarily with the Trap command I Gto set up a "trap" or "failsafe" mechanism to catch those nasty little N Linsects that somehow manage to take their vacation inside of your perfectly working program. KRefer to the Trap command for more complete information on using SYSERR to trap bugs. KThe following is a list of possible SYSERR values, both in decimal and hex N values, with the string of what is printed out when Metal has such an error. SYSERR values:; Error Text Number (Hex) Number (Dec)< ------------------------------ ------------- -------------2 Syntax $80 1282 Missing Symbol $81 1292 Missing Data $82 1302 Device Number out of Range $90 1442 Range Error $91 1452 Data Type Mismatch $92 1462 Command Type Mismatch $93 1462 Integer Overflow $A0 1602 String Overflow $A1 1612 Bad Dispatch Call $A2 1622 GOSUB Stack Over 127 $B0 1762 RETURN without GOSUB $B1 1772 FOR/NEXT Stack Over 8 $B2 1782 NEXT without FOR $B3 1792 DO Stack Over 8 $B4 1802 UNTIL without DO $B5 1812 END IF without LONG IF $B7 1832 WHILE Stack Over 8 $B8 1842 END WHILE without WHILE $B9 1852 TRAP Table Full $BA 1862 Unable to RETURN from a RUNSUB $BB 1872 Unable to RUN a Module $BC 1882 Variable Memory Full $D0 2082 CPU Stack Overflow $D1 2092 Undefined Label $D3 2112 Global Label not found $D4 2122 Unable to allocate main RAM $D5 2132 Bad CALL Format $D6 2142 RAM Area Not Allocated $D7 2152 Unable to load package $F8 2482 Unable to load external $F9 2492 Unable to run ASM package $FA 2502 Program Halted $FE 2542 End of program $FF 255 See also: DOSERR, SYSERR$, SYSINFO, TRAP SYSERR$ Type: string function result$ =SYSERR${( value a$=SYSERR$( print "Error number "x" is "SYSERR$(x) KSYSERR$ is used to pull out the string version (verbalization) of the last J Hsystem error or the given value . If no value is used, then the last P NSyserr value is used, since Metal assumes you want to see what last caused an error. See also: SYSERR, SYSINFO SYSINFO Type: system value result =SYSINFO( value x=SYSINFO(1)" if SYSINFO(2) goto OutputAborted* if SYSINFO(4) and x$="!" staff=not staff KSYSINFO (SYStem INFOrmation) is used to read a wide variety of information P Nabout the system - what key was last pressed, what key caused output to stop, number of errors, etc. JAll SYSINFO values are read-only - they cannot be set, since they reflect 9 changing conditions inside the language and the system. Here is the list: KSYSINFO(1) This SYSINFO returns back the ascii code of the last key hit. C ANote that is does "eat" the keystroke from the buffer - it B @is still in the buffer, and will stay there until you remove it % (either via Get a$ or Clear Input). MSYSINFO(2) Returns back the ascii value of the key that caused text output = ;to stop. Only valid if Abort$ was equated to something. If < :Abort$ is null, or no key was hit to cause text stoppage, SYSINFO(2) will be zero. MSYSINFO(3) Returns back the number of keys in the input buffer. If this is ( zero, then there are no keys in there. MSYSINFO(4) Returns the "Local Sysop Mode" flag. This can only be changed C Avia pressing openapple-L from the BBS keyboard. If this value is @ >1, then the sysop has gone "online locally" (and the user has A ?been "lost in limbo" for the duration). Once the sysop presses A ?openapple-L again to return from Local Mode, this SYSINFO goes back to zero. ISYSINFO(5) This counts the number of System Errors (crashes) that have ? =occurred since Metal was started. Resets to zero only when Metal.System is re-launched. KSYSINFO(6) This returns the "Iduhno" value that was set initially in the C AMetal.Config file (sysinfo(6)=). This Iduhno value can only ; 9be changed either by modifying the Metal.Config file and 9 7re-launching Metal, or by pressing openapple-1 through > command. Instead of returning a number, it returns a string. KSYSINFO$(1) returns the last key hit in string format. No case conversion B @takes place on this, thus if the user hit "k", then "k" will be A ?reported back, not "K". If there are no keys hit (nothing left A in the buffer or whatnot), then this will return a null string. KSYSINFO$(2) returns the key that aborted text output in string format. If A text has not been aborted, then this will return a null string. SYSINFO$(3) returns the version of Metal - "METAL v1.23.45", for example. JSYSINFO$(4) returns the current CIB file being run. Yes, yes, this seems C Asilly and really unnecessary, but please look at the STND.SUBS file in Future Vision and then think about it. See also: ABORT$, CLEAR, GET$, SYSINFO defghijklmnopqrstuv O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== Metal Commands : Section "A" Metal Commands : Section "T" Page Type: buried command print TAB( to_pos char$ print TAB(50)"Over here!" print name$;TAB(40,".");score LTAB is used to move the cursor over to a given column number. If no char$ Lis given, then TAB will use a space to print out. TAB can only be used with the Print command. See also: PRINT TCOPY Type: complex command KTCOPY filename$ or # device {TO filename$ or # device } {FOR lines {UNTIL match$ } {LEN chars TCOPY news$ TCOPY #1 to #printer TCOPY #msg For 23 NTCOPY (Text COPY) is used to print a text file out from the disk to somewhere P Nelse - normally, the screen, but you can send the output to the printer or to another file. LIn it's simplest form, without any of the optionals, TCOPY will simply dump N Lthe file to the screen until it reaches the end of the file or a ascii code E of zero (a control-@, called the "eof byte") is hit. Then it stops. However, you can change how much TCOPY will dump and to where it will dump. LIn order to use a file, you must either give TCOPY the filename of the file N L(for example, news$ or "2/welcome.message") or the file channel to be used. M KThis is considered the "source" file, and is always the first parameter in the TCOPY list. IIf you supply the source filename$ , then TCOPY will open the file, and K Istart dump from the first byte of the file. If, instead, you supply the O device , then TCOPY will assume that you have already Open'd the file, and N Lwill begin dumping starting at the current filemark of the file (handy if = you have random-access files with messages buried in them). HIf you wish to re-direct output somewhere other than the default device G E(normally, device #0), then you must supply the TO filename$ or TO device optional. HUsing TO filename$ will cause TCOPY to create the "target" file if it K Idoesn't already exist. It then opens the file, and output will go there, L Jstarting at the first byte , overwriting anything that may already be in that file. NUsing TO # device allows TCOPY to dump to the printer (#printer) or anywhere L Jelse. If a file channel (#1 through #4) is used, then TCOPY will use that C Aopen file, starting output at the current filemark of that file, 3 overwriting anything that may be at that point. KChanging how much TCOPY will output is accomplished by using the FOR, LEN, and UNTIL optionals. KThe FOR lines optional allows you to change how many lines of text TCOPY J Hwill output. Normally, this defaults to zero (dump it all), but you may P Nchange this to limit the output to say, 20 lines or whatever. The valid range for this is 0 to 255. HLEN chars allows you to limit the number of characters output (this P Nincludes control characters). Normally, this defaults to zero (no limit), but I Gyou may only want up to, say, 4000 characters dumped out (for whatever : reason). Once that limit has been reached, output stops. GUNTIL match$ will cause TCOPY to take a look at the characters being M Kprinted out and see if they match this string (case is important). If they O Mdo, output is stopped. Thus, if you use UNTIL "-EOF-", TCOPY will stop if it P Nsees "-EOF-" somewhere in the flow. This can be buried - for example, say the O Msource file had "Suddenly, the screen flashed -EOF- and everything stopped." O Min it, and you were looking for "-EOF-". TCOPY would stop right after it had I printed "...flashed -EOF-" - anything else afterwards would be ignored. FSee also: APPEND, BLOAD, BSAVE, CLOSE, CREATE, DEVICE, DOSERR, FCOPY, B FILEMARK, FILESIZE, FLUSH, INPUT, OPEN, POSITION, PREFIX$, PRINT TEXT Type: command TEXT LThe command TEXT is used to reset the local video display to a known state. M KIt resets the screen to 80 columns and 23 lines, normal text, with the top F Dstatus bar in place. The screen is cleared and the cursor is in the upper-left corner. HIt has no effect on the remote user and affects no other aspects of the system. See also: CLEAR, PRINT, VID THEN Type: buried command expression THEN code if x=1 THEN goto xisone MThe THEN command is used with the If-Then-Else syntax of coding. Please note H Fthat Metal really doesn't care if THEN is in the If-Then or not - the L language is "smart" enough to handle programming with or without the THEN. See also: IF, ELSE TIME$ Type: system value result$ =TIME${( value print "It is "TIME$: x$=TIME$(clock(1,2)):print "You have spent "x$" online." HThe TIME$ command is used to either read the current time or to build a M time-like string based on a number (generally passed from a Clock command). LReading the current time is simple - simply read TIME$ without the optional value NIf you wish TIME$ to convert a time value - like what the Clock commands pass P Nback - give it the optional ( value ). The value must be expressed in total seconds. This means value is equal to: Hours * 3600 + Minutes * 60 + Seconds. See also: CLOCK, DATE$, DAYNUM Type: buried command for j = 1 TO 50 print a$(1) TO a$(9) tcopy #1 TO #printer fcopy f1$ TO f2$ mode(0) DThe TO command is used in several other commands as a place holder, N Lseparating parts of the command syntax into easy to use pieces. It is never N Lused on its own, and will generate a syntax error if you try to use it as a * command or as part of a math expression. See also: FCOPY, FOR, NEXT, PRINT, TCOPY TRAP **Type: flow control command TRAP condition link label TRAP syserr goto Crash TRAP clock(5) goto TooLong TRAP doserr gosub DiskHit KThe TRAP command is used to allow the program to catch certain conditions, K Iranging from the serious (a system error) to the not-so-serious (loss of P Ncarrier). You can have multiple TRAPs and multiple levels of each trap at any given time. LThe condition parameter consists of a single command or a set sequence of commands. They are as follows: condition means --------- -----9 CLOCK(1) Clock timer number 1 runs out to zero9 CLOCK(2) Clock timer number 2 runs out to zero9 CLOCK(3) Clock timer number 3 runs out to zero9 CLOCK(4) Clock timer number 4 runs out to zeroJ CLOCK(5) Clock timer number 5 (keytimer clock) runs out to zero- DOSERR (almost) any ProDOS error= DOSERR= value If Doserr equals this certain value, trap8 MODEM Change (gain or loss) of the carrier; MODEM=5 Gain of carrier (system gets connected)8 MODEM=6 Loss of carrier (user drops carrier)$ SYSERR Any system error= SYSERR= value If the system error is this certain value9 XFER If remote system starts Zmodem, trap. MWith Syserr and Doserr, you may TRAP for certain values or any value. If you J Htrap for a certain value, Metal will check for that value when the trap 9 "activates" before going with the "any value" option. KClocks 1 through 4 run all the time, and are checked as needed. Clock 5 is N Lonly used and check when the system is waiting for a keypress (such as with Get or Input). KThe Xfer trap is used for when the remote system starts up its Zmodem Send P Nprotocol. Zmodem sends out a series of characters (usually *rz[cr] or rz[cr]) P Nto tell the other computer it's sending files. By using TRAP XFER GOTO Zmodem J Hyou would have Metal automatically go to a routine that starts a Zmodem N Lreceive. This trap is handled whenever the keyboard is being read (when the cursor is blinking). FTraps are checked once each time a "line" of program code is run, and 0 whenever the system is waiting for a keypress. HOnce a TRAP activates (say, on a system error), that particular trap is K Iremoved from the list - the other ones are still in effect, though. File M Kchannels that were open are still open, the Gosub/Return stack is still in L Jeffect, etc, etc. Your "Trap Handler" routines may need to close the open files off. KAfter you give the TRAP command the condition , you must give it a link Fcommand word - either a Goto, a Gosub, or a Push. Each one is handled differently. NA Goto will unconditionally run the routine when the TRAP activates. There is K no way for your Trap Handling routine to know where the TRAP happened at. LA Gosub will fake a Gosub to the Trap Handler - a Return out of the Handler : will resume the program from where the TRAP happened at. NA Push will push the routine into the Gosub/Return stack, and the next Return L Jwill run the Handler. This can be used to modify existing flow control is esoteric programs. LAnd finally, the given label is the name of the routine that is to handle J that particular TRAP when it happens - this is the Trap Handler routine. See also: FOR, IF, GOTO, GOSUB, LONG IF, ON, PUSH, NEXT, THEN, UNTIL, WHILE xyz{| O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== Metal Commands : Section "A" Metal Commands : Section "U" Page UNHIDE Type: command UNHIDE {RETURN} UNHIDE UNHIDE RETURN The UNHIDE command undoes the HIDE command. LThe first form of UNHIDE is without the Return optional. Used in this form, O MUNHIDE undoes the last HIDE command, deleting all of the current variables O Mand retrieving the older variables. This also has the effect of freeing up a L Jlarge amount of memory, since what was needed before to duplicate off the J Hvariables is no longer needed. Like HIDE, UNHIDE will not mess with the Gosub/Return stack. JUsing UNHIDE RETURN will retrieve the old Gosub/Return stack from memory, N Lreplacing whatever is current. You should be extremely careful with this, M Ksince you can HIDE RETURN, run another program, and then UNHIDE RETURN and 0 then watch your program go into critical mass. See also: HIDE, RUN, RUNSUB UNTILA Type: buried command / flow control command / second part of DO UNTIL condition tcopy parameters UNTIL string$ UNTIL rec>50 tcopy f$ UNTIL "-game over-" KThe UNTIL command is used in two areas: as the second part of the Do-UNTIL 7 loop, and as the UNTIL optional in the Tcopy command. IIn the first form, as the "closing" part of the Do-UNTIL, the Do command - starts the loop, and the UNTIL finishes it. NThe Do-UNTIL loop will, well, loop, until the given condition becomes true. M KIn the above example, until the variable "rec" goes past a value of 50. As E long as "rec" is less than or equal to 50, then the loop continues. LUNTIL is also used in the Tcopy command to tell Tcopy to look for a certain 9 string and stop output once that string is printed out. See also: DO, END, TCOPY, WHILE O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== O==<====<==<==<====<=<====<====<====<====<====<====<====<====<====<=<==<====<=== Metal Commands : Section "A" Metal Commands : Section "V" Page Type: math function result =VAL( string$ x=VAL(i$) if VAL(zx$)>20 goto TooHigh HThe VAL command is simply used to turn a given string of numbers into a J Hnumber so that you can perform some math operation on it. VAL will work P Nthrough the string and build the number until it runs out of characters or it 7 finds a character that is not a number (0 through 9). LIf the first character of the string$ is not a number or is not the minus 4 sign ("-"), then VAL will return a result of zero. VAL is considered the reverse command of STR$. KSee also: ABS, ASC, BITVAL, HEXVAL, INSTRING, LEN, MEMAREA, MEMSIZE, PEEK, B @PEEKADDR, PEEKBYTE, PEEKWORD, PADDLE, RANDOM, ROTL, ROTR, SIGN, STR$, SYSINFO VID$ Type: system variable result$ =VID$ VID$= filename$ VID$(1)= prompt$ x$=VID$ VID$="" VID$="*/VT100.MAP" VID$(1)="" MVID$ is used to either see what Emulation Mapper is currently loaded, change ? the Emulation Mapper driver, or to set the Page Pause String. MReading VID$ will return a string that is stored inside the currently loaded P NEmulation Mapper driver - normally, this will return something like "PTSE" or J H"ProTerm Special Emulation", which means the system is processing N ProTerm Special Emulation codes and is passing them directly over the modem. MSetting VID$ to a null string will reset the Emulation Mapper to nothing - J Hthe default condition. In this state, Metal will process or "Map" O MProTerm Special Emulation control codes to any other terminal emulation - it ' will pass them directly to the modem. KSetting VID$ to a non-null string will cause Metal to attempt to load in K Ithe given filename into memory. Metal checks a few bytes of the loaded O Mdriver to make sure that it is a real Mapper driver, and then sets things up N Lso that all ProTerm Special Emulation control codes are sent to that Mapper O Minstead of to the modem. The Mapper will check convert these codes into what = the emulation it is supposed to be working with can handle. JSetting VID$(1) to a string will set up the Page Pause Prompt string that P Nwill be display if VID(15) is set to 1 and VID(16) is set to some value. This P Nstring will be display each time the screen gets "full" between keywaits (Get P Nand Input). The given prompt$ can have control codes in it to highlight the prompt. See also: EXT, VID, Emulation Mapping Type: complex system variable result =VID( number VID( number result x=VID(7) VID(13)=0/ if VID(14) print "Sysop already being paged." MThe VID command is used to change the way the local video emulation and some J Hof the remote text output. Through this, you can change the size of the 6 screen, the cursor character, the page pausing, etc. KThere are sixteen possible values for the number parameter. Here is what each one does: number does ------ ---- JVID(1) This is the width of the screen. Note that for the most 9 7part the video driver will ignore this, as most of the > >