--------------------------------- LDos V1(3) for AMOS1.3 and above. LDos is (C) Niklas Sjöberg 1992 --------------------------------- PART SIX - Misc commands ------------------------ Lpp Mem - Determine how much memory a file crunched by PowerPacker will need to decrunch. SIZE=Lpp Mem(END) where END is the end of the previously loaded file. It must not be the end of the bank, but the end of the file, Start(Bank)+Lsize("FileName"). (AMOS's banks are always rounded off to the nearest multiple of 4 and may differ from the actual filesize) No check is done to see that the bank really contains a powerpacked file so make sure you have loaded one before. Lpp Decrunch - Decrunch a PowerPacked datafile. Lpp Decrunch START,END To DEST where START is the start of the loaded file, END, see above. The file will be unpacked to address DEST. This bank must be at least Lpp Mem bytes large. Again, no test is done to see if the bank really contains a powerpacked file! Be careful! Llargest Free - Return the size of largest block of free memory A=Llargest Free(TYPE) where TYPE is either 0 for CHIP-memory of 1 for FAST-memory. A will contain the size of the memoryblock. This value is NOT the same as the AMOS commands Fast Free and Chip Free, they return total unallocated memory-size, not the largest size you can allocate in one bank. Always use this command before reserving a larger amount of memory in a single bank. Lrun - Run a program. A=Lrun("command(s)","WINDOW") where "commands" is the program(s) you wish to run. Since a new CLI is opened to execute your program(s) you may wish to set the stack for the program, and you MUST set the fail-level (with failat) to a very high value, otherwise a program may fail with a returncode >0 and the Shell/CLI-window will never be closed! (at least not until the user types endcli >NIL:) After every command a linefeed, Chr$(10) MUST follow. "WINDOW" is a standard CON:/NEWCON: (please always use CON: since NEWCON: isn't used any more in Release 2) with the normal syntax : "CON:x/y/xx/yy/name" name should preferably not contain any spaces. To use Lrun you must have the following commands on the disk (system:) : c:Run c:NewCli c:EndCli (c:FailAt) You also must have assigned t: to somewhere or have a directory named "t" on the disk and have the disk write enabled. An example : T$=Chr$(10) A$="Failat 10000"+T$ A$=A$+"Stack 8000"+T$ A$=A$+"Lha l dh0:download/*.lha"+T$ A$=A$+"Wait 2 secs"+T$ : Rem, pause to read the output A=Lrun(A$,"CON:10/10/600/180/AMOS-Output") where A will contain any number (see Technote below). Please note that you should NOT use EndCli as the last command, Ldos will automatically append this. Always make sure that the requested commands exists on disk, because there is no way (that I currently know of) to ignore a "command not found"-error and your script will fail, leaving the window open and AMOS waiting. If you follow these rules you will be enable to run just about every program from AMOS! Note! Under KS1.3 a "unknown command"-error always breaks the CLI on my system. I do not know why, it works perfectly well under KS2.04 and other 1.3-systems if FailAt has been used. Technotes: Some of you might wonder why it takes so much to run a program? I will try to explain a bit.. Normally Execute() in dos.library is used to start programs. Execute() use the command Run in order to start the program (that is why you have to have it available on the boot-disk). It SHOULD also be possible to pass two channels for I/O, for example a newly opened CON:- window. Now there has always been troubles with Execute() because if you wish to use an inputchannel Execute won't complete until EOF (End Of File) is written to the inputchannel. Since an EOF never is sent the input/output-window is never closed, and Execute waits, and waits..and waits. The only way to make Execute continue is by typing EndCli >NIL: in the window. I tried sending a string like "dir dh0: opt i"+LF+"EndCli >NIL:"+LF (LF=LineFeed) but this didn't work if the program just executed fails. Failat also needed to be used. At this time I realized you would need a whole script (EndCli, Failat, Stack etc.) to execute a program. It seemed much smarter to write all the commands to a script- file, and use NewCli FROM script-file + a window specification. This way you can execute a number of commands and the I/O re- direction is taken care of automatically! All this works fine, but two new problems arose. First I haven't found any way of getting hold of the returncode from Execute() since it now returns directly after the NewCli-command is run (a new process is created). Secondly, control would return to AMOS directly, and one newer knew when the script was finished! I still have no idea of how to get hold of the returncode from the executed programs in the script but the other problems was solved in this way : 1) Your commands is written to a script-file, t:ld.t 2) Two commands are added "t:sig_ldos" and "EndCLi >NIL:" 3) A program called t:sig_ldos is created by Ldos in t:. 4) A messageport is created by Ldos. 5) A NewCli is launched FROM t:ld.t CON:?/?/?/?/Title 6) Ldos directly start to look for a message in the msg.port. 7) The script reaches the line t:sig_ldos. 8) sig_ldos send a message to Ldos that script now is at the end. 9) EndCli is executed, the window close, Ldos cleans up and control returns to AMOS. Sometimes it can be hard to start a program correctly on a multitasking computer....... Lexecute - Start a program which doesn't need CLI I/O A=Lexecute("programname") Works almost like Lrun above, but only one program may be run. The program to be run can not use any CLI-I/O. Started programs should open their own screen/window to function properly. Lexecute is perfect for starting editors, wordprocessors or just any other program which isn't designed to print or receive input to/from a CLI-window. If the program detatches itself control will return to AMOS directly. where A will be True if successful, False otherwise. Ldisk Font - Load a font from disk, making it directly available to Get Rom Fonts A=Ldisk Font("name.font",SIZE) where name is the fontname, ".font" MUST follow it. SIZE is the size of the font you wish to load. A will be >0 if the font loaded OK. If a <1 the font wasn't on the disk or already in memory. Since this routine is designed to always try to scale the sel- ected font with a best match, it may return true even though the requested font wasn't available. Say you try to load diamond/10, (which doesn't exist) then diamond/12 will be loaded instead. ++ Note that above ("designed fonts") may differ a bit depending on ++ which diskfont.library you have. A nice feature of diskfont V36+ ++ is that you may specify a full path for the fontname and thus ++ don't have to have the font located in fonts:. Always make use of ++ V36+ routines if you can.. To bad for those who haven't upgraded ++ but they probably will :) *- Lcrypt - Encode a buffer containing data. *- Lcrypt START,LONGS,"password" *- where *- START is the startaddress of a bank and LONGS is the length *- divided by four. Fx LONGS=Length(10)/4. "password" is your secret *- code which also is used to DEcode your data later. Please note *- that an error will be produced if the password is less than 4 *- characters long. Also note that the password is casesensitive! *- Ldecrypt - Decode a buffer containing coded data. *- Ldecrypt START,LONGS,"password" *- See above for more information. *- A word about cryptation : *- Using crypted data on a computer (or anywhere) is never 100 *- percent safe. If somebody really wants to decode your data he *- will simply load his favorite monitor and single-step your *- program at machine-level until he finds either the code or the *- decoded data itself. This however demands quite some skill and *- patience and can be very time consuming. Data coded with Lcrypt *- uses quite a simple formula which easily can be picked up in the *- code, however, even though the algorithm is know there a millions *- of combinations that have to be tried if the password isn't *- known. There are about 4300 millions of different combin- *- ations... To make your code VERY hard to crack try to follow any *- (or more) of these steps. *- 1) Use non-visable codes as password (linefeed, tab etc. *- etc.) *- 2) Don't type the password like A$="MyPassword". This can *- easily be spotted in the code. Try using Data's reading them with *- an special offset (use each third char or something) *- 3) If you HAVE typed your code directly in the source you could *- always do something like A$=A$-" "-"a"-"M" which makes it very *- much harder for a "single-stepper"-cracker to follow at machine- *- level. *- 4) First code half your bank with one password, the other half *- with another and then code the whole bank with a third. *- 5) Code Powerpacked files or Powerpack your coded files. *- 6) If not compiled, lock the procedure containing the code and *- decryption part. *- Normally you wont have to take any of these steps, most people *- haven't got the skill or the time to mess around in your *- programs... *- Lset Var - Assign a value to a global environmentvariable. *- T=LSet Var("Name","VALUE") *- THIS FUNCTION REQUIRES Release 2. *- where *- "Name" is the name of the variable (must not exceed 50 *- characters) and "VALUE" is a ASCII-string containing either *- digits or text. The value-string must not exceed 50 characters. *- This function will return true if successful. Name of the *- variable is not case-sensitive. *- Lget Var - Get the value from a global environmentvariable. *- A$=Lget Var("Name") *- THIS FUNCTION REQUIRES Release 2. *- where *- A$ either contains the value (or text) or is empty. If A$ is *- empty the variable didn't exist. Name of the variable is not *- case-sensitive. *- Ldelete Var - Remove a global environmentvariable from memory. *- T=Ldelete Var("Name") *- THIS FUNCTION REQUIRES Release 2. *- where *- T will be true if a variable with the name "Name" was found *- and removed. If T is zero the variable didn't exist. *- Lansi - Convert ANSI-sequences to AMOS's format. *- S$=Lansi(A$) *- where *- S$ will contain a sequence containing AMOS control characters. *- A$ is a normal ANSI-sequence which doesn't have to be complete if *- the rest of the sequence follow in the next call(s). *- Currently supported ANSI controlcodes : *- ANSI-sequence RESULT *- ------------- ------ *- $C (*) Clw/Home *- ESC[n;n;n;nm Style, foreground or background. Lansi detects *- if style or colour is to be changed. It is legal *- to omit any of the parameters as long as you *- specify at least one, and end the sequence with m. *- Supported styles are: Italics (shaded), Inverse and *- Underline, other styles are simply ignored. Please *- note that changing from one style to another *- doesn't turn off the last used style. To reset to *- pen-colour 1, background-colour 0 and no style, use *- ESC[0m. *- ESC[0 Cursor invisible, ignored *- ESC[0 p Cursor visible, ignored *- ESC[xA Cursor up x lines. x may be omitted. *- ESC[xB Cursor down x lines. x may be omitted *- ESC[xC Cursor right x columns. x may be omitted. *- ESC[xD Cursor left x columns. x may be omitted. *- ESC[y;xH Locate x,y. y may be omitted. *- ESC[x@ Insert x spaces. x may be omitted. *- ESC[L Insert line. *- $a Linefeed. Passed on to AMOS. *- $d Carrige return. Passed on to AMOS. *- $8 Backspace. passed on to AMOS. *- ESC[2J Clw. To my knowledge it isn't possible to support *- "Clear window at cursor" so even if only ESC[J is *- printed the whole window is cleared. *- ESC[K Clear line at cursor. *- ESC[M Clear line. *- (*) $C really isn't a ANSI-code but is supported since many *- BBS-programs (and AmigaDOS + others) use this. *- How it works: *- The Lansi-routine is a 'smart' routine which remembers old *- incomplete sequences and codes. This means that you may 'Print *- Lansi("ESC[0");' (ESC means Chr$(27)) and nothing is output on *- the screen! If you directly afterwards execute 'Print *- Lansi("m");' a string which resets style and colours will be *- printed (it isn't visible). Lansi doesn't buffer the actual ANSI- *- sequence but rather store datas in its own format and it is thus *- very important that the ANSI-sequence is valid since Lansi can't *- 'go back and check'. The most important thing in the ANSI- *- sequence is the sequence-terminator, like "m" for colour/style *- or @ for insert etc. Lansi will happily collect and convert data *- until a sequence-terminator is received and return nothing to *- AMOS if it isn't received. This may result in lost characters if *- no valid sequence-terminator is sent. *- Speed & Problems: *- I have tried to make the Lansi-routine as fast as possible and *- this have resulted in TOTALLY unstructured code, more labels than *- a grown up man can count and repeated codesections instead of *- slower/more general subroutines. Because of the many sections in *- the code which writes to a temporary destination it is *- (currently) almost impossible to add an effective routine which *- checks for overflow. This means that you must be very careful *- when using Lansi with files with very long lines. Programs like *- DiEd (ANSI-editor) may output an animation which is one line *- 'long' and over 10 kb big! Lansi has no way to figure out how *- big the finished string will be. The internal buffer used by *- Lansi is 2000 bytes big so in general lines up to 400-500 *- characters is ok. Sometimes the resulting string is shorter than *- the ANSI-sequence but I have still not added support for repeat$ *- so the ANSI-sequence ESC[99A will evaluate to 99 bytes. I will *- look into the possibility of making use of repeat$ later on. Right *- now I'm more than happy that this routine just works :-) (I know *- that anybody who has tried to write ANSI-emulation know what I *- mean...) *- Now, what do you gain on my sloppy and unnecessary large code? *- I made a comparison between typing an animationfile in Shell and *- printing it using Lansi in AMOS. Both routines used a 4 colour- *- screen. The file I tested with was Per-Anim_Animation which is *- included with DiEd by Per Raue. The file is 11760 bytes long and *- mostly contains movementsequences and about a half screen of *- text. I was equipped with some fastmem, an AdSpeed and a fast HD *- in both tests. *- Type Per-Anim_Animation took: 09.52 *- Type >NIL: Per-Anim_Animation took: 02.46 ----------- *- Actual time excluding loading 07.06 *- Lansi with output took: 02.02 *- Lansi without output took: 00.76 *- Please note that these figures may have changed since you got *- Ldos since I'm still changing in this part of the code. I now *- also have an A3000/25 to test with :-) *- Both Lansi-testroutines used Lset Eoln and Lstr to split the *- file into 1357 lines (every cursor movement). Lansi gained some *- hundreds of seconds since it didn't need to process bold, on the *- other hand it had to split (and load from HD) the file in 1357 *- lines, allocate stringmemory etc. The time was measured using *- 'Timer' in AMOS and the timingfunction in Csh. The AMOS-program *- was run uncompiled. CONTINUED IN NEXT ARTICLE.