{TRUN is a program that runs Turbo .CHN type files from CP/M. Wait a minute...why make .CHN files at all? Turbo, after all, generates .COM files that run directly from CP/M. The problem is: each Turbo .COM file takes a minimum of 8 kb on your disk (for the Turbo runtime library). You can save 8 kb/file by generating .CHN files instead, but now you must have a way of running these. To do this, compile TRUN.COM, then compile your program YOURPROG.CHN. (Use the same start and end addresses for all files.) Now, from CP/M, type A>trun d:yourprog And you're in business. Written by Jim Zisfein and uploaded 10/14/85 to the Blaise Pascal RCP/M, (212)-604-1930, for the public domain. Please send comments, addressed to me, to the Blaise Pascal RCP/M.} label boot; const cr=^M^J; {If you type A>peace b:with.you at the CP/M prompt, PEACE.COM is loaded and run, and memory locations $005c to $005c+11 are loaded with information about file WITH.YOU on drive B: (ref: Lindsay J, Introduction to CP/M Assembly Language, Hayden, 1984, p.38). This region is called the file control buffer (fcb).} fcb=$5c; var n: integer; {all purpose variable} entrycode: byte; {returned by bdos calls #17 and #18} chainfile: file; {file variable for .CHN file} filename: string[14]; {name of .CHN file} {The direct memory address (dma) is where CP/M will, on command, retrieve information on the disk directory (ref: Lindsay, p.43).} dma: array[0..127] of byte; {Writeentry prints a directory of .CHN files on the logged disk. "Start" is the location within the dma array where CP/M placed the file name} procedure writeentry(start: integer); var n: byte; begin if (char(mem[addr(dma)+start+9])='C') and (char(mem[addr(dma)+start+10])='H') and (char(mem[addr(dma)+start+11])='N') then begin write(' '); for n:=start+1 to start+8 do write(char(mem[addr(dma)+n])); writeln; end; end; {TRUN - main program} begin {TRUN first attempts to chain to the file in the fcb (see above). This file, named "filename", consists of an optional drive name, a 1-8 character file identifier, and the .CHN extension.} {The disk drive, specified in the CP/M command line, is indicated at fcb+0 as follows: 0=none, 1=A:, 2=B:, etc.} if mem[fcb]>0 then filename:=char(mem[fcb]+64)+':' else filename:=''; {The 1-8 character file name resides at fcb+1 to fcb+8. These characters, exclusive of spaces, are added to "filename".} for n:=fcb+1 to fcb+8 do if mem[n]>32 then filename:=filename+char(mem[n]); {Finally, the .CHN extension is added} filename:=filename+'.CHN'; {If TRUN can chain to "filename", it does so, and you're finished.} assign(chainfile,filename); {$I-} chain(chainfile); {$I+} {If it can't, e.g., if you entered A>trun on the command line, then you get a directory of the logged disk and a chance to try again.} if ioresult>0 then begin end; write(cr,'TRUN routine to run Turbo .CHN files',cr, '------------------------------------',cr,cr, ' Syntax: A>TRUN B:GARBAGE (if GARBAGE.CHN is on B:)',cr, ' or: A>TRUN B: (gets directory on drive B:)'); {And again, and again, until you chain the file or the file chains you.} repeat {The directory is obtained by making bdos calls: #26 to set the dma address, #17 to get the first directory entry, and #18 to get subsequent directory entries. Calls #17 and #18 return "entrycode", which indicates the directory entry offset in the dma (entrycode*32) or if no entry found (entrycode=255).} write(cr,cr,'Please select a Turbo .CHN file from list below,',cr, 'or drive identifier (e.g., B:) to change default drive,',cr, 'or CPM (to quit).',cr,cr); for n:=fcb+1 to fcb+11 do mem[n]:=ord('?'); bdos(26,addr(dma)); entrycode:=bdos(17,fcb); while entrycode<>255 do begin writeentry(entrycode*32); entrycode:=bdos(18); end; {User makes selection} write(' CPM',cr,cr,'Enter filename, drive identifier, or CPM --> '); buflen:=14; read(filename); write(cr,cr); for n:=1 to length(filename) do filename[n]:=upcase(filename[n]); {"CPM" quits} if filename='CPM' then goto boot; {If drive selected, then drive # placed at fcb and deleted from filename, also disk reset (bdos #13) performed.} if filename[2]=':' then begin mem[fcb]:=byte(filename[1])-64; delete(filename,1,2); bdos(13); end; {Drive prefix reinserted, .CHN suffix appended, and attempt made to chain} if mem[fcb]>0 then filename:=char(mem[fcb]+64)+':'+filename; filename:=filename+'.CHN'; assign(chainfile,filename); {$I-} chain(chainfile); {$I+} {If at first you don't succeed...} until ioresult=0; boot: end.