' JJJJ ?\>' L-=l>  ԠéԠˠ#~?  xDIR ERA TYPESAVEREN USER!yO#< Ty#O 3ǯ21y_͸2y2ͽ:ķ˜1͘A͌>>͌92^ :˷¥.!_~#fow]ɭʎʥ!v"!çREAD ERRORçNO FILE^:˷#͘*~ "Ʒ"͌#>?͌͘ =_.:;<> Oƅo$>!Y2*O"ʉ@G:ʐ:wÖx2p0ʹ#*©6?ëw˜0ï#6 ¹.0#*6?w0#6 #6"  Ň!˶2:2a{_:˷ʖ:˷>Ľʖ:=2–!B!6#5ʖ:˷Ľ!ͬʧ )!F#xʺ~0wëw!" !~6ͽ:ý(!\XSUBMIT STARTUP COPYRIGHT (C) 1979, DIGITAL RESEARCH _͌> ͒> Ò> Ò͘~#͌ì _2<į2:mD:/!i; !i;/:>:(y2E!|"*wɍ`?M^EE??++ ԩ ŭ ?  JL ``LLLÓãݯ`i>2:! >*|559=DM@|m}m>2:j*~#bxA!>:!>:!>a>2! "ía>2!"*" *>::*!~#*">>a n& $Lq<`ΧԠĠڸčԠԠ͠Ԡ؍2>o:= gw8H<8H=` }Hx / hJ Leh<> > @A @A>i =<>+ LeÍڍh@(L>*// -П( ( $8` %  ZNx`. }x$50x.$50xL JJJJ`Hjf5 }h $50x`  Ȍ` Hx  -(hL(h8֩`Lx (`H݌hHhHh݌>?F؅G(jf5(  ;  R( FGj 0x j $xxH` ( Rh RL.xxH h  !"#$%&'()*+,-./0123456789:;<=>?x&& 8 , P ; ' / \ ; & ; x)*++`FGG8`0($ p,&" cI꽌ɪVɭ&Y & &Y &   꽌ɪ\8`&&꽌ɪɖ'*&%&,E'зЮ꽌ɪФ`V0 ^ *^ *>`+*xS&x'8*3IxiU ,>J>V J>V `8'x0| &HhHh V Y V '&Y V x ꪽV ' `Hh` ! ~ 3#0 Wx x ƀ Ƃ G ~ # 3x~#B!Y~ɯ2:˷=!˾ý:˷=!˾:ý^T!~  6?#ˆ:`O> K{͘A͒>:͒͢>:͒͢xK > K > ͒x  ͢ØÆ^ BRͧ9!5‚#~Y‚#"T<ÆALL (Y/N)?^ Tʧ͘!6!~ڇ ɯw4!Y~ʆ͌†t=ʆf ^ T ɯ2o&)|+!<ͧЯ2*C!!~~#~O~G#n,-.‹! w! yG!x͢.:E<ʄ! q!pQ:E<. ʄ$.:E<ʄi6}2ExN! ~态O>G~G!~G} *C!r#r#r ^ͥ_y#x#{2>2T*CGͻ:ẅ́n>2;O ^DM;}H>"*C :ٷ:ddslO s#r:EϷ͊:==»y==»*Ww#*"͸*:G#š"͸:!پw4!iw:Z!E~=26 w ~>2!E5T*C!"C"C!w# F! w͌xѯ2͢*C ~<wʃG:٠!٦ʎì 4~ʶ¬:<ʶ$ʶïZͻЯx>2>2ͻ:!پZկ2:EϷẅ́͊Ͳ> *C ^OT *C~wD -'  -@ͦ~^*C Ox! N!Fwyxʋ>ڋ>*Cw~#+w#w+ɯ2E22i^ *C :ٷ~w~͔͔# # ::/GyO>2!q*C"͡ʔ*JҔ^:Oyʃ?|x | sӖ-|N-# S:2E!~Яw>T D^6k-äPYy 5*{zBK5:AϾ#~$=2Ek͌ ):BO!yoxg*:BO}!N#F "*#*s#r^ ~!J! J*:مo$*C~i6iw**{#zr+s{ozg**͕** Ѿ,w͜͸Ͳ!!N#F$**O!~#O: \зSЀ*C :ٷqn& ^#V>O^"*}:*)=":O:١o"*C *C!ͮ~2~2ͦ:٦2ͮ:ЯO:فw:w |g}o*ٯ# 2E>! ^#V w#P:BO|^#V#"##"##"##"!O*!O*|!6ʝ6>گ*w#w*w#w'û*ڷ! J*""!N#F*^#V*~#foyx*{_zW+*x: 2 p&x~+é7ͯ2 H! >w_: ! Ͼ5ͤNkͱ¦ͱxʊ#Nx: Ϸ! ϖ2 ͤ! 5™#wO~x½p Hy<< ڷʑ :!qMD# O͐  :ϷE B 2>: Ϸb# : Ϸy! 4 5~yy5 6yҐ^H@Oy H H: –ͬ  #H: ! Ͼ Hù H H $O͐: 2 *CN# ʽ̙̥̫̱"C{2!"E9"1Aϯ22!ty)K!G_^#V*Cΐ~؃E؜إث ,&-AGMSϛ!!ô!ô!Bdos Err On : $Bad Sector$Select$File R/O$:BA2!~6=qf^!~2>`~2˯2\!!B!~> >#0~O#Cx2͘1)ͽÂf zͧÆBAD LOADCOMf^: !˶ Â$$$ SUBÆNO SPACE^ :Ty!B*O=?_s#"^sG!~Yʸpsp2mÆÆf ͧÆFILE EXISTS _: É: :˷ʉ=2)ͽÉ T!@k!}|qs+p+q-*C ͥ!!q#p#w*:BOYG}*MD "ã:!BϾw!>2*C~=2u:B2~2wE:A*C϶w>"!""ٯ2B!"!rQQQâ~?ͦ~?rQ*"CQ-Q͜QüQrQ$Q*):B"*)*)Q;*"E:;:A2AQÓQÜQ*C}/_|/*٤W}_*"}o|g":ٷʑ*C6:ٷʑw:2E**E}DQ>2C0T"I !>"H>2J: !͢:d::d!s~B#1!P!J߇o~,foɷp:BB Apple ][ CP/M 56K Ver. 2.20 (C) 1980 Microsoft ;ۯ2>EE??++B#1!P!J߇o~,foɷp;ۯ2:޷;ۯ2e ]~6(*} *:޽ y(3:޷s:2G<2x/a2:oa":޷zޯ2{![:޷ <2:>sɯ2>!>2!;:*     1>2>2*"?ۯ2:08 !"Y"BT"->2:8Y"/:8Y"F~!xq!;`~0,~!M;!x~>.~8[q>:޷ 2y2!!{o!:=8 ~y!3w.y2Cɯ2>!w#w#wOa."y .:g"*"!~((5:# :*޽ :޼ $| 8g,"ޯ2!"_!ޅoN!޷((+! ~O#O:x >2ޯ2:޷*(*D*:wk*(:$_"~28 ?@wx( !;!܅ony 2$8!2E!y>>?22!ɯog"$2E!.B...X&*}(8.|8&"$պ`~(,qy2E[22G: 2:O*:P!O#~#'۹~y/:02?"2O: K*:*(0**:8'(*:08* *: 8(*7!w˹#~(=5:!( +_ywɷ+ͱ*:]lc_O{- OMG!~_ :( 6>83! ~èCfuÇKmVÉÎÓãݯ`iޓښ:ޓڦJޓڲZޓھjޓzޓߊ / !~ `66= !; !{g1:Q!͢گ22>2!"2!"͎>2RESOURCEDOC RESOURCEDOC !RESOURCEDOC"#$RESOURCECOMO%&'()*+,-.TPA COM/-CPM/DOM000 CLEAN DOC APHAYES ASM100H. It goes thru 1700 or so, then the stack. At 1800 is a 512 entry table for control commands. Each is 3 bytes long, and controls the format of the re-sourced list, i.e. is it DB, DS, DW, instructions, etc. At 1E00 is the start of the symbol tabl ---------------- RESOURCE commands are inconsistent at best. - RESOURCE is a kludge based on years of disassembler experience and hacking, and was never "planned" - just coded sitting at a tube, and modified over 2 years before being contributed toINDEX ASMRXYZ[\]^_`abINDEX DOCXcdefghijklmAPXMODEMDOC'xy|}~INDEX COM !NEW CAT Please use it in the spirit in which it was contributed: to enlarge your understanding of the micro- computer world around you, and to allow you to customize programs which you legitimately own, for your own use. "Semper non rippus offus" ---- MAST BAKAPBOOT2 ASM APMODEM COM!6noAPXMODEMCOMpqNOLF PATSTDKEYBDPATAPMODEM DOC,rstuvwTHOUGHT hout good software is useless to 99% of us. Most good software has to be paid for. I strongly support the legitimate purchase of licensed software. I do not regularly use any programs which I have not purchased. (Yes, I do occasionally "try" one, the CP/M UG. For example, to kill a symbol: k.label but to kill a control value: caddr,k and to kill a comment: ;addr, but RESOURCE does the job like no other I have seen. ---------------- N-O-T-E: Pardon the editorial, but I feel hardware witNOTE: any command taking a hex address (Dnnnn, etc) may take a value in the form .label but arithmetic may not be performed. (i.e. d.start is ok, but d.start+8 not) ---------------- Overall structure of RESOURCE: It is a .COM file, which runs at RESOURCE A disassembler for 8080 programs by Ward Christensen CP/M U.G. 1/80 6/1/80, correct typos. 02/24/81 Doc add'l commands: '.', '/', A, C(H), etc. flagged with ====> then the date Suggestions? Call me eve's at (312) 849-6279 MLIST50 COM z{MAST CATCAT COM(FMAP COM )*INDEX ASM"#$%&'+,-./01237UCAT COM45INDEX ASM89:;<=>?@ABCDEFGINDEX ASMHIJKLMNOPQRSTUVWbut then buy it if I plan on using it). I have been asked by software businesses to NOT distribute RESOURCE - because of it's ability to produce good .asm source quickly. But, there are so many disassemblers out, why not a good, conversational one? e. It has no defined length as such. If it is not used, it occupies only 2 bytes. If you want to re-source something which is in memory, such as a PROM, a program previously loaded in high memory, "CP/M itself", or whatever, you can just do so. Hol entry in at the address of the LXI. You might also delete the incorrect "I" entry which RESOURCE stuck in (typically at the second byte of the LXI) ====> 02/24/81 comment: Since "A" now builds "I" entries for any label JMPed ot CALLed to, in. It says 4E00 2100 which means it came into actual memory to 4E00, but 2100 if we are talking with respect to loading at 100. Thus, we could set our comments table up after the .COM program - say at 5000: U5000 The ? command shows the memory u100 or L100 it dumps or lists what LOOKS like your program. Internally, RESOURCE is adding the offset to the D and L addresses. What should you set the offset to? Well, that depends upon how many symbols you will use. O1F00 will load the program ailding ctl entries for all JMP/CALL/LDA/STA/LHLD/SHLD in- structions, you must now-and-then purge the ctl table of redundant I and W entries, by using the "/" command. * Comments overflowing into BDOS (ug!!) * Using an offset which is not in fhighest memory you may use. (Note if you have, for example, an empty 4K memory board in high memory, you can Use THAT for comments). Let's take an example: You have an 8K file, FOO.COM which you want to disassemble. It will have about 300 labels. owever, typically you want to disassemble a program which runs at 100H, which is were RESOURCE runs. Bob Van Valzah would have solved that by making resource relocatable and moving itself up under BDOS. I wasn't that industrious. Instead, RESOURCEk. If you are not sure what it is, typing O will tell the current offset. Hoo, boy! Hope this kludge of documentation is enough to get you going - hmmm, better give you some of the gotcha's I've discovered... ---- WATCH FOR ---- * Symbols tilization for control, symbol, and comments entries. (no, I never put in anything to keep track of the .COM - you'll just have to do that yourself). If you ever want to dump real memory, you'll have to reset the offset to 0: O0 but then set it bact 2000, thus allowing only 1E00-1FFF for symbols, i.e. 512 bytes or about 50-60 labels. If you didn't leave enough space, then used B to build a default symbol table, the table could run into and clobber your .com file! (easy recovery, however: just ree memory and overlaying BDOS or whatever. * The B(uild) command gobbling up too much when building a DB: "B" will take a DB 'GOBBELDY GOOK' followed by LXI H,FOO and take the LXI as a '!' (21H) so you'll have to manually stick a new "I" contr300 x 10 is 3000, or call it 4K (what's a K unless your tight). The symbol table starts at 1E00. 4K more is 2E00. Let's load the .COM at 2E00, so since it normally starts at 100H, the offset is 2D00. O2D00 is the command. We then RFOO.COM to read it uses the concept of an "invisible" OFFSET. After all, what do you care where it is as long as it LOOKS like it's at 100h? So, you set an offset. O2F00 sets it to 2F00 Hex. Reading a .COM file (RFOO.COM) causes it to come into 3000 on. If you say Doverflowing into the .COM. (Use ? command to see how full symbol table is) * Control entries overflowing into .SYM (altho I can't believe anyone will have a program with more than 512 control entries!!!) ====> 02/23/81 comment: With "A" now buinto the disassembled program, you will have to designate an area to Use for the comments. The U command (e.g. U4000) specifies what area is to be used. Before issuing the O (offset) command, do: L5 7 which will show the JMP to BDOS, which is the change the offset to being higher, and read in the .COM file again) Each entry takes 3 bytes + the symbol length, and if you like 7 byte labels like I do, that means 10 bytes/label. An offset of 2F00 should be adequate. If you want to put comments some of these problems "might" fix themselves up. * Trying to dump real memory without setting the offset back to 0. (then forgetting to set it back to its proper value) * Forgetting how big the .COM file you are disassembling was. * Usin ---------------- ; Put comments into the program. (must execute 'u' command first, to assign area for comments to be placed) ;addr,comment enter a comment ;addr lists existing comment ; lists entire comments table ;addr, deletes existi, and another K... SO... Here's my "wish list" ..it might save you telling me YOU think such-and-such would be nice... * Targets of LHLD, SHLD should automatically be flagged as type DW in the control table. Ditto LDA and STA as DB or asse you have a control entry for a DW, resulting in: DFLT: ;172C DW 100H but somewhere in the program, the following exists: LDA 172DH Even if you did a B and have a label L172D, it won't show up since it's in the middle of a DW. ity to, in one instruction, rename a default (LXXXX) label to a meaningful name. 02/24/81 ====> Done. Just entering a label for a given address automatically replaces any other label at that address, and notifies you "replaces .xxxxx" -----racters in a row, he fires off a DB from then on until he runs out of those characters. Suppose your program was 200 long (ended at 3FF), and you had zeroed (aha! Nice DB candidates) memory there (there meaning at your offset address + whatever).g RESOURCE to rip off software (yes, I know, you heard that before, but only 3 in 100 needed to be told, and 2 in 100 needs to be told again, and 1 in 100 doesn't give a rat's fuzzy behind anyway!!) * Forgetting to take checkpoints when disassembe!! but not implemented that way: just do E6C,+ and I'll scan from 6C back until I find a label, and calculate the offset for you. Only works back, i.e. resulting in a label+offset. * The comments facility should be enhanced to allow total SUBST second half of DW. Ditto targets of LXI as DB (?). ====> 02/24/81 Done!! (not the LXI part) * E5C,.FCB followed by E6C,.FCB+ should automatically calculate the appropriate displacement, and put it in the symbol table. 02/24/81 ====> Don Instead, do this: e172d,.dflt+1 put in the new label as a displacement off the beginning. ====> 02/24/81: The old label will be replaced, you no longer have to kill it first. ====> 02/24/81 mod: You could now type "e172d,+" and RES----------- RESOURCE types an "*" prompt when it is loaded. You may then enter any of the following commands. Each command is a single letter followed by operands. Commas are shown as the delimiter, but a space will also work. ---------------- Then you QB100,400 and viola!! RESOURCE overlaid your "E" control with a "B". ---------------- RESOURCE is relatively complete. (well, actually, the phrase "rampant featureitis" has been "mentioned"). ...But there's always another dayling large files. You may even want to rotate the names under which things are saved: STEMP1.SYM STEMP1.CTL STEMP1.DOC ====> 02/24/81 For simplicity, I have added: STEMP1,* as being equivalent of the above * Missing a label: SuppoITUTION of entire line(s) of the code, i.e. at address such-and-such, replace the next 3 bytes with the following arbitrary line. This would help those "how do I explain what was being done" cases such as: LXI H,BUFFER AND 0FF00H * Add the abilte that while this disassembles and reassembles properly, it is not "as correct" as the technique used in the previous item. * Having the "B" command overlay your "E" control entry. What? Well, "B"uild is pretty dumb. If he finds 8 DB type chaOURCE will back up to the nearest, previous label, and stick in the proper offset for you(!!) * improperly disassembling DW's (see previous item). You might be tempted to make DFLT a DB so that DFLT: ;172C DB 0 L172D: ;172D DB 1 Nong comment note that '\' is treated as a new line, i.e. \test\ will be formatted: ; ;TEST ; ---------------- . Sort the symbol table. I believe that the label = "FOO" belongs before the label "FOO1". I did not realize that was a char A-Z or 0-9, or "+" or "-". This allows: E5D,.FCB+1. Note the "+" is not checked, i.e. E5D,.FCB+2 would be wrong (assuming FCB is at 5C) but would be allowed to be entered. 02/24/81 ====> Note if you enter two symbols for theich means a new line will be started. Thus if you have a string in memory which disassembles as: DB 'Invalid operand',0DH DB 0AH You might want to change it putting the 0DH,0AH together on the second line - just enter a "B" control entrysymbols into RESOURCE. / Deleted redundant "W" and "I" entries from the ctl = table, to compress it down. Right now the ctl table only has 256 entries. This means the format of your program (i.e. DB to DW to instructions, to DS, to DB, etc) m ---------------- dump: - dxxxx Dumps 80H from xxxx on daaaa,bbbb Dumps from aaaa thru bbbb d,bbbb Continues, thru bbbb d Continues, 80H more NOTE 80H is the default dump length. If you have a larger display, you can change the default mats) ---------------- Control table usage: - c dump ctl tbl cnnnn dump from starting cnnnn,x define format from nnnn to next entry. values of x: B = DB (attempts ASCII printable, 0DH, 0AH, 0) 02/24/81 ====> new: (H) H =universal idea until I found SID generates a sorted label list with blanks sorting AFTER non-blanks. Since RESOURCE scans for an exact match on symbol lookup, stopping immediately after passing the correct position, a symbol table generated by Sel or control break in the middle of a DB string, I don't find the comment. Solution: Put a Cxxxx,B or Cxxxx,H entry in the control table if you want a comment. I don't con- sider this a serious bug, as you typically are commenting a field wi for the address of the 0DH. The same technique could be used to make DB 'TYPESAVEDIR ERA REN ' appear as DB 'TYPE' DB 'SAVE' DB 'DIR ' DB 'ERA ' DB 'REN ' 02/24/81 ====> I just found a bug: If you have comments, but not a labay only change 256 times. This should be adequate. See "A" command for tip. ---------------- Attempt to find DB's/DW's/Instructions while listing. - This command works just like 'L', but attempts to find DB's of 8 chars or longer. (see 'via: d=nn nn is the HEX new default. For example, a 24 line tube could display 100H: d=100 or.. d=100,200 Defaults to 100, dumps 200-2ff ---------------- enter symbol: - ennnn,.symbol symbol may be of any length, and contain any DB with only hex operands W = DW (attempts label) S = DW to next ctl entry I = instructions K = kill this ctl entry E = end of disassembly NOTE every control entry causes a "control break" (NO, RESOURCE was NOT written in RPG) whID will not always have labels found by RESOURCE. Also, LINKASM (my hack to allow a LINK pseudo-op), puts out "poorly" sorted labels, i.e. I didn't know how to efficiently sort them, except by first letter, so you MUST use "." when loading LINKASM th a label, anyway. The slowest thing RESOURCE now does is to hunt the entire symbol table for every byte of a DB looking for a label, so having it search the comment table too, would slow it down, even more. But I'll likely fix this some day. y stop and type the / command to delete redundant entries. ---------------- Build default sym tbl (LXXXX) labels for each - 2 byte operand encountered. Note 'B' is identical to 'L' except labels are built. (see 'L' command for operand forL' command for operand formats) 02/24/81 ====> I now "catch" the operands of all JMP and CALL (also conditionals), LDA, STA, LDAX, and STAX, and put a control entry in for their operand. This fills the control table quite quickly, so periodicall same address, RESOURCE will delete the old one and tell you that it did. A label which is spelled exactly the same as an existing one will replace the existing one even if the addresses are different, and won't tell you of the substitution. ets take an example: A friend sends you a .COM file. It contains a 1K image of a PROM of his, which runs in his system at F000. Thus, you would like, under RESOURCE, to say LF000, and see the first byte of his PROM. So, first, load the .COMdress, (L or L,nnnn) then the output file will continue uninterrupted. 02/24/81 ====> Make sure you have the "E" contol entry if you do Lnnnn,FFFF; Previx the L with a "Q" if you want quiet mode, i.e. do it to disk (if writing enabled via Snam Press any key to stop. f continue previous find command fnnnn find nnnn starting at address you last stopped at in the f command ---------------- H or RESOURCE has gotten so full of rampant-featuritis, Hx I finally added a help commane a .COM file which really isn't an image of a program running at 100H, its a little hairy to calculate what the offset should be. Substituting whatever one value is unknown, in the following formula, should allow you to figure out what offset tstop when that address is found. This allows you to 'lstart,ffff'. The 10 line default may be changed via: L=nn where nn is a HEX line count, e.g. L=14 set to 20 lines/screen You can change the default and list, e.g. L=9,100 Dflt t02/24/81 ====> You can generate "label+nnn" for any label within 129 bytes AFTER another label, by saying exxxx,+ for example: e5c,.fcb to define fcb e5d,+ to define fcb+1, the start of the name, e68,+ to define fcb+12, the ex- offset for disassembly - o print current offset onnnn establish new offset (note the offset is always added to any address specified in an a, b, d, or l command. to dump real memory, the offset must be reset to 0 (O0) before the dump.) e.ASM) but not to the console. You may do dump commands, and others, without affecting what is being written to disk. 02/24/81 ====> See also the "A" and "B" commands, which are "L" commands which take additional actions. ---------------d which gives a brief explanation of each of the command letters. You may start with a particular letter by following H by that letter, i.e. HR for help on R command. Be ready to use ^S to keep the help from scrolling off, and DON'T use ^C to so type: Offset2 = Offset1 - Startadr Where: Offset1 is the original offset used to load the .com file Offset2 is the new (different) offset issued Startaddr is the starting addr. of the module. Now that you're as confused as I, lo 9 lines, list at 100. NOTE when using L to list the .ASM program to disk, you should either list the entire program at once using: Lssss,eeee or, you can list small pieces at a time. As long as you list again without specifying a starting adtent byte (altho bet- ter as e68,.fcbext) ---------------- Find occurrence of address or label. Note this function - runs until interrupted (press any key). fnnnn,ssss find address nnnn in memory. Start the search at ssss. Runs forever. 02/24/81 ====> When disassembling something that is in its right location in memory (as opposed to loading a .COM file for RESOURCE to work on), just leave the offset to 0. Ex: disassembling a PROM, or looking at your current BIOS. If you hav .ASM file save via 'SFILENAME.ASM' command l lists 10 lines from prev pc lssss,eeee lists from ssss to eeee l,eeee lists from current pc to eeee lssss lists 10 lines at ssss Note that if you have a control 'e' entry, then the list will top it - you'll reboot. Just hit any character. (I use space or c/r) ---------------- kill symbol from table - k.symbol ---------------- list (disassemble). This command is used to list the - file, or to list it to disk after enabling the file in, say with offset 4000 (O4000). Thus Offset1 is 4000. Then calculate: Offset2 = Offset1 + 100 - Startadr or Offset2 = 4000 + 100 - F000 or Offset2 = 5100. Thus issue: O5100 to set the new offset. Then, LF000 lists (wahl, I'l , and think of it as if your program were actually at 100. D100 will dump your program. also note: if the program being "RESOURCEd" will have a fairly large symbol table, then you will have to set the offset higher: o2f00 or some such. (the -- use area of memory for comments table - unnnn such as ud000 if you had an open board at 0d000h, although more typically you would (U)se memory after loading the .COM file and determining where it ends. ---------------- purge sym t - ORG instruction, and equates for any label outside of a given low-hi address pair. (the start and end addresses of your program). e.g. if disassembling from 100 to 3ff, it will generate 'fcb equ 5ch' if FCB is in the symbol table. In typical 2200, which means the program will read into 2200 + 100 = 2300. ---> rtest.com reads the com file into memory. system says: 2500 0300 which is the actual hi load addr, (2500) and the original hi load addr (300) REMEMBER this address (300) (note 'u' command must have been issued) 02/24/81 ====> rfilename.* will load first the .SYM, then the .CTL, then, if you have issued "U", the .DOC file <==== ---------------- save .asm, .ctl, .sym, or .doc file - sfilename.asm use 'lbe durned), the first byte of his PROM. Let's verify WHY this all works: LF000 computes the REAL memory address to list, by adding in the offset. Thus, F000 + 5100 = 4100, the real memory address being dumped. Is that where the PROM really i----------------------------- Here is a sample of the RESOURCE usage. Given: a COM file (lets say test.com) which runs at 100 (as any good COM file should), and goes thru 2FF. lines preceeded with ---> are typed by you. 02/24/81 ====> Because obl and CTL tbl x - ---------------- close .asm file (note that a preferred way to close the .asm file is to have specified a control entry for the end address (e.g. c1ff,e)) z - -------------------------------------------- ---------------use, you would 'sfilename.asm' then use the P command to write the prolog, then the L command to write the program itself, then, if there was no "E" control entry processed, a Z to close the .ASM file. Pstart addr,end addr quiet command: any because you might want to put a "E" (end of assembly) control entry there. <<<>>> that all 'L' (disassembly list) and 'D' (dump) commands work with the offset added. Thus, you should learn to forget that the disassembler is in memory' command to write, z to end sfilename.CTL saves the CTL table stablename.sym saves the sym file sfilename.doc saves the comments table 02/24/81 ====> sfilename.* will write the SYM, then the CTL, then the DOC files. <==== --------------s? Yes!! Because you used a 4000 offset to load the .COM file, and .COM files have an implicit 100H offset, i.e. 4000 loads at 4100. (Whew!) 02/24/81 ====> end of added comments ---------------- prolog generation - this routine generates an f added function (primarily the help command) RESOURCE has GROWN! Thus rather than me re-writing all the "2200" displacements below, just consider that for practicality, it would have to be more like 3000. ---> RESOURCE ---> o2200 set the offset to by taking a pass thru the program: QB100,xxxx ---------------- read .com, .ctl, .sym, or .doc file - rfilename.com reads in at offset+100h rfilename.ctl loads the ctl table rfilename.sym loads the sym file rfilename.doc loads the comments tablecommand which is preceeded by a q - will be done 'quietly'. For example, to save a .asm program, you could just do: ql100,3ff or ql100,ffff if you have set the 'e' control in the control table. Another use is to build a default symbol table ? command will show symbol table usage: if your symbol table is nearing the .com file, then just set a new offset (higher) and re-load the .com) if you want to dump r-e-a-l memory, you would have to reset the offset to 0: o0 (but don't forget to(and "A") put in a control entry cnnnn,e which defines the address of the end of your program. The l command will then automatically stop there, and in addition, if you are in 'save xxx.asm' mode, the output .asm file will be closed. If you do mot dple db's in a row need not have separate cnnnn,b instructions, but that these do cause a 'line break', i.e. if you have a table of ascii commands, for example: 02E5 DB 'LOAD' 02E9 DB 'SAVE' the disassembler would disassemble these as: 02E4 DB 'L'a' command may be used to automatically find the db's, but you must then check them to insure that they don't extend too far. All printable characters, 0dh, 0ah, and 00h are considered candidates for ascii db's. At least 8 characters in a row must ds instrucion references only up to the next label. This means that multiple ds's in a row must each be explicitly entered into the control table. Presence of a label is not sufficient. 02/24/81 ====> Thought I might say why: because scanning the dump as: 0100 c3170144 4f50xxxx xxxxxxxx xxxxxxxx *...copyr ight....* 0110 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx *xxxxxxxx ........* thus you would want to instruct the disassembler to switch to db mode at 103, and back to instruction mode a reset it to 2200 before continuing with your program.) If you are disassembling something which is in memory at it's correct address (such as looking at ccp) then don't set the offset. It defaults to 0 when dis is first loaded. ---> l100 list yable lookup is done to determine if there is a label at that location, and if so, a new line is started. 02/24/81 ====> Remember the bug: it doesn't look for comments in the MIDDLE of a DB. Thus if 'loadlit' and 'savelit' were in the symbol table, aOADSAVE' you could put in an additional control entry: c2e9,b, which would cause the disassembler to generate: 02E4 DB 'LOAD' 02E8 DB 'SAVE' which is much more readable and realistic. Note that before generating each byte of a db, a symbol tbe found to make sure that long sequences of mov instructions won't be taken as db's. 02/24/81 ====> "A" command now finds DB and DW and instruction entries based on instruction types and operands; Remember to use "?" to see how full the control tasymbol table for each address in a DS would be very time-consuming, and RESOURCE might sit for minutes in a large program, scanning thru the DS. ---- steps, continued: After building the control entries with cnnnn,b and cnnnn,i 02/24/81 ====> t 117, thus: c103,b c117,i 02/24/81 ====> (Actually, "a100" would do that for you!) Continue doing this, bracketing every ascii db which is in the middle of instructions, by a b control instruction and an i control instruction. Note that multiour program - lists "about" 10 lines. ---> d100 do a dump of your program. NOTE that typically here are the steps to disassembling a program which has just been read into memory: Use the dump command to find the ASCII DB areas. Note that the s the labels on the 'load' and 'save' above, no separate 'b' control instruction would be required as the label would cause the break. <<<>>> that at this time the automatic label checking is n-o-t done for ds instructions. Make sure that eached to scan the program for ascii db's yourself, use the 'c' (control) command to set the beginning and end of ascii areas. For example, a program which starts out: 0100 jmp start 0103 db 'copyright .....' 0117 start ..... would show up in theble is getting, and "/" to periodically compress out the redundant entries. Use the cnnnn,k command to kill erronious entries put in the control table by the a command, but then immediately put in the right address, such as via cnnnn,i if you wantefine a control 'e' entry, then you will have to use the break facility (02/24/81 ====> That's not clear: I mean pressing a key, such as return or space, NOT ^C!!) to stop the l command (don't use control-c as that will re-boot cp/m). If you were writihe file is opened. Any subsequent a, b, or l command will have whatever is listed written to disk. Encountering a 'e' control, or typing a z command will then close the .asm file. The listing may be interrupted, and continued. Since the l command tCF,.DKBUF to put the symbol in the table. 02/24/81 ====> or: E7CF,.DKBUF to put the symbol in the table. C.DKBUF,S to start the DS C84F,B to define it's end, and <==== Continue, iteratively using the 'l' command and the 'c' and 'e' commanduild labels) instead of l (for list program). The b commands causes lnnnn default labels to be inserted in the symbol table for every 2 byte operand encountered (LXI, SHLD, JMP, etc). It will undoubtedly make some you don't want, such as L0000. You ym rtemp.ctl uxxxx (such as u4000) rtemp.doc 02/24/81 ====> or now: RESOURCE o2200 uxxxx (such as u4000) rtemp.* <==== This will take you back exactly where you left off. If you want to save a .asm file out to disk, do the folloble, all data from there on will be taken to be DW's. 02/24/81 ====> Watch for out-of-sync DW's, i.e. if you have a sequence: DW DB DW and only have a control entry for the first DW, you'll get a DW for the DB, and will pick up the second DWng an .asm file, you would have to user the z command to close the file. Next, you would list your program to determine how it looks. when you recognize a routine by it's function, insert a label. For example, if you saw that location 7ef was a cha. To save a control file: sfilename.CTL (any filename, may include a: or b:) To save a symbol file: sfilename.sym To save a comments file: sfilename.doc (not ".com" of course) 02/24/81 ====> To save all three: sfilename.* NOTE thats until you have the listing in a nice format. You will then probably want to save the control symbol, and comments tables. Or, you could have been saving them at checkpoint times (so if you make a major mistake you could go back to a previous one)will have to: K.L0000 kill label L0000 from the table. When you encounter data reference instructions, try to determine what type of area the instruction points to. Typically,, LXI instructions may point to a work area which should be defined aswing: Make sure that there is a control entry defining the end of the program (such as c200,e) or else you will have to specify the ending address and manually type a z command to close the file. sfilename.asm A message will indicate that t in the middle. <==== Suppose that you determine that address 7cf is a 128 byte buffer for disk I/O. You want it to disassemble to: DKBUF ;07CF DS 80H You do this as follows: C7CF,S to start the DS C84F,B to define it's end, and E7racter out routine (type) then enter a label into the symbol table: E7EF,.TYPE NOTE that all symbols start with a '.', so as to be dis- tinguished from hex data. NOTE that if you want the disassembler to make default labels for you, use b (for b the filetypes must be used as shown, but that any legal filename (or disk:filename such as b:xxxx.CTL) may be used. You could now control-c to return to CP/M, and come back later to resume your disassembly: RESOURCE o2200 rtemp.com rtemp.sC534,W 02/24/81 ====> Hooray! Resource now does that LDA/STA/LHLD/ SHLD, JMP and CALL operand reference - ctl settings for you! NOTE that whatever mode you are last in will remain in effect. Therefore if 534,w is the last entry in the control ta a DS, or to an ASCII string, in which case we will have already made it a 'b' control instruction. Operands of LHLD and SHLD instructions should be made DW instructions. For example if you encounter LHLD 0534H, then issue a control instruction: ypes only 10 lines, use laddr,ffff to list thru the end of the assembly (assuming the "E" ctl is present), or use Laddr,xxxx where xxxx is the real address-past-the-last-instruction. If this is the 'final' save of the .asm file, you will probably wag as help Hx Start help listing at "x" command K.symbol Kill symbol from symbol table L Lists 10 lines from prev pc Lssss,eeee Lists from ssss to eeee L,eeee Lists from current pc to eeee Lssss Lists 10 lines at ssss L=nn nn is hex list have never forgiven them for killing Allied, from whom I could buy almost anything I needed, from recognized national brands, etc). (Tee hee, I just saw a sign on a RS store door saying "Realistic: the truly NATIONAL brand". They don't fool me!) 02/24/81 ====> Deleted comments about having to kill a label when entering a new one for the same address. The system does that for you. here are some more commands: ? prints statistics on symbol and control table usage, etc. c prints the ld default sym tbl (Lxxxx) C Dump ctl tbl Cnnnn Dump ctl starting at nnnn Cnnnn,x Define format from nnnn (B,E,I,S,W) Dxxxx Dumps 80H from xxxx on Daaaa,bbbb Dumps from aaaa thru bbbb D,bbbb Dump thru bbbb D Dump 80H more D=nn nn= Heunting on) but I got a call from the other who said "I've now moved to Ft. Worth, and am employed by TANDY to write a disassembler for them. May I use you program as a base? I asked TANDY if they were interested in buying your program, and they said,nt to put an 'org' at the beginning of the output file, as well as generate equ instructions for any references outside of the program. For example, a typical cp/m program will have references to: bdos at 5 fcb at 5ch tbuff at 80h the 'p' (foror Allied". 'Nuff said. ZOSO: You have some competition, but I am but a humble 1%... ------------------------ RESOURCE, by Ward Christensen "Quick" command summary Any address may be replaced by .symbol i.e. D.START ;addr,comment What am I doing editorializing in this RESOURCE DOC file? I dunno, just had to say it, I guess. Oh ya, what the heck, I just found a person in a RS store who knew what he was doing: It took me so by surprize, I had to ask. He said "I used to work fentire control table cnnnn prints the control table starting at address nnnn ds dumps the symbol table. Interrupt it by typing any key. ds.symbol starts dumping at the specified symbol, or the nearest symbol. thus "ds.f" starts thx dump size default. Ds Dumps the symbol table. Ds.symbol Sym dump starting at .symbol Ennnn,.symbol Enter symbol into table Fnnnn,ssss Find address nnnn starting at ssss F Continue previous find command Fnnnn Find nnnn H Give this listin No, just write another from scratch". Boy! Did that shake my confidence in humanity. Considering my anger at Radio Shack for 80% of the crap-ola I have bought from them being "chintzy", working poorly, breaking easily, etc (and more importantly, I prologue) command generates the org, then scans the symbol table and generates equates: ORG 100H BDOS EQU 5 FCB EQU 5CH (etc.) additional commands: if you entered a label in the symbol table but now want to get rid of it: k.symbol Enter a comment ;addr Lists existing comment ; Lists entire comments table ;addr, Deletes existing comment . Sort symbol table / Delete redundant ctl entries A(see "L" for operands) Attempt to find DB's/DW/Instr B(see "L" for operands) Bui lost MODEM: by everyone else changing it, and not having my own latest changes. I HAVE given source to RESOURCE out to 2 hobbyists, who said they would keep it, and change it to Z-80 for me. 2 months later I hadn't heard from one (Who'm I'm still coe dump at the first label starting with the letter 'f'. ....have fun, and let me know of any problems or suggested improvements. What about Zilog-80? Well, I continue to make changes to the source, and would hate to "lose" RESOURCE the way Idefault # of lines O Print current offset Onnnn Establish new offset Pstart addr,end addr Generate program prolog Q Before any command suppresses console output: QB100,200 Rfilename.COM Reads in at offset+100h Rfilename.CTL Loads the ctl + q1‹͉*̈́ "6#6 S++NO, THAT WOULD OVERLAY THE DISASSEMBLER BECAUSE OFFSET IS TOO SMALL:  ʇ ʇ ʇ s#r## ʺ ʺ w#ç pÇ  f: 0))))of ͌" .͇>2!.nt as comments * !O~  ‹"!O~ ʋ S,S ‹# ‹*##~+~+w~~w#~w+##~#oa$a:5/2\2h!O:P ʋ:³:O@2\##]~*"Ç~ #.~ .#> >2;2< ;DISK NAME TITLE FLAG DB 'W' ;WIDTH DW STWDTH ;SET WIDTH HANDLER SCSIZE: DB 80 ;SCREEN WIDTH DB 'V' ;REPORT VERSION DW VRSRPT DB 0 PC =* SOFFSET=* *|G SCOMNTS=* * SCTLTBL=* ~###24#~.Z EQU ~%+~T%W>H24##~ #ͬd>26N !O~# ‡Congratulations, you found the patch area!**"!O~ Sʜ=,*"  ,‹#table Rfilename.SYM Loads the sym file Rfilename.DOC Loads the comments table (after "U") Rfilename.* Reads the SYM, CTL, and DOC files. Sfilename.ASM Save .ASM file. Write w/L, Z to end Sfilename.CTL Saves the CTL table Sfilename.SYM Saves th*͖+###~29IgE #^#V*Q"D24SʔHBWS: INVALID CTL ENTRY ͵24[#{ʋ22~#,8 8 Ë:/o: /g#>24ZDS |%}>H"[>24ZDW **^#V*##"[[2:<24ZDB *>2<2;2<2;24:22 !O~ [,O O=q" [ O,‹#" 2 ͬ: o:=}* :: :;**:NMž>A2Nê~#ž~#Ҫ+ *>Bͫ>Iͫ*|*##F>24͏#~\<== 103H IS RESTART ADDR RESOURCE by Ward Christensen (AS OF 03/03/81) (C) Copyright 1981 Type H for help, -H to delete help $"Permission for non-commercial use and distribution of object code granted"1(# p x24262!1(ͬQ>24ZEND 24:5>Ͳp25S++ASM FILE CLOSED++ ͌:5/"e >2!.͇n .‘ *̈́ "##6:! +͇q1͇( *:5 \ :« S++TRUNCATED TO AVOID BDOS OVERLAY++  "*"*" ‹*ͬ ~#}}}.~ TV>.#}hI"::##",  Ë!P~.´Dҷ*F÷*^#V#~ F#~#ͬ÷:727SNo Saddresses will prie sym file Sfilename.DOS Saves the comments table Sfilename.* Saves the SYM, CTL, and DOC files. Unnnn Use nnnn for comments table X Purge all symbols and control Z Write eof to .ASM file ? Prints statistics (sym, ctl, comments) *:9H~ 6  r 6 %>H::2:; 0#*#":DS :E *͖::2:>,>'::<2:~~'#*#":D  :E *͖ ::<2:&  +~# ~  >'E >'[SSYMTBL=* * SI#")wG#w#<w#2*D}!&"/OxGwx># 1"##6S++Already deleted++ !N*"SY/N purge all symbols & CTL?:NYNt!O~ ʋT ,‹#>24Z ORG z%{>HT ‹*##~++~#~ !N~ ʸ=ʕ-.N;ʹ/ABCʕDʽEʻFʏ HI8KL MNO PʪQvRD S UXtZ ? S? :O ڋ2SC/R = L command 2O:2N:,S++Help has been deleted++ :OHd:H!6r *O^#V#~#G6 V > Ͳ~Ͳ# > Ͳ> Ͳ >Ͳp:!:eD+͇/zͲzͲ{Ͳ{ò+/1%‹>2524OS++WRITING .ASM ENABLED Use Lfrom,to (or QLfrom,to for quiet) to list to disk Use Z command or E coD *H|$\!+~#"HIS++UNEXPECTED EOF >w$\\<ʋ2|!"H\œ\ > >*_:6:5!4{IJ{ PSW* ~* ~!N ~o$>0~#4NZZ.NCC.POPEP.M.BCDEHLMAACI.ADC.ADD.ADI.ANA.ANI.(C...'CALL/CMA.?CMC.CMP.CPI.'DAA. DAD.DCR. DCX.DI..EI..vHLT.IN..INR.INX.(J...'JMP.:BSEH:=Kʋ‹*~###<###*|/g}/o+++^!+~{@z@`is#r#:=w##wS++CTL TBL FULL: INVOKING "/" TO COMPRESS IT++ *~#+<7#z+¬{###Ù͖û*ͬ^#V#z<G ͖~#>: >,~#û`i"##6#~#$+D-D0<:A<[ʋ+:<*2*##N#ʜbk ##~#ʜʌ~͢ڪÓO͢ʪڪÓ͢ڪ^#Uͬ:*N>2*~O++!OÓw# w#w# 0 # #"_!* BENW`lþ%TZ`t͊͊͊͊ͅo͊* #" * ~ ڢ[Ң:=ڢҢ~>'͊͏~ ڳ%>H0͊* ~͔͖ͅ:<4:7͊͏z>0 zntrol to close the file++ ͉*##6* S++NO FILE ACCESSES PERMITTED UNTIL .ASM CLOSED S++UNEXPECTED EOF !eâ!ew# Œ!O~ ʸ/-P@ ʲ ʿ,‹#~ͽ*(͖S++None to change, I went back #r*T]xo|g"##6++DM*F{,z3 "s#r#p#w;*##~#ʌx‚O͢qڌ~#oI$I++ѷO͢eÌH͢ʌe++"F7*~#¤~ʳ#~7#oҙ$Ù#~#G7!O~ ,‹#~+.‹͚! "">2xV͖GLDA. LDAX*LHLDLXI.@ MOV.MVI.NOP.ORA.ORI.OUT.PCHLPOP.PUSH R...RAL.RAR.RET.RRC.RLC. RST.SBB.SBI."SHLDSPHL2GSTA.STAX7STC.SUB.SUI.XCHGXRA.XRI.XTHL!L6L#z{!LDs*~#<#~IW#!#O*^#V#z,Ͳ~Ͳ> Ͳ> Ͳ#5>Ͳp:!1͇*ʪ,ʞ:ڎ0))))o}s#r#w#w6#6:!G Ë ͉!O~;#~ 9# 3 ,‹d~ *s#r##w|}> ~09 +- , ~#+9-F+Tz/W{/_~#ʴ.ʸ$@~*0ڋ:ڇAڋGҋ0))))o#l~*0ڋ:ҋbk)))0_|W#Õ>22Dڋ^#V*#~!"H2|\H{ %0 ͊:;:=͔JO>Iͽ>WD>BDͫ%ͫ͊* ~0͊* ~ͅ~H>,> >;* #^#VZDB >2=v* ~!> ~#~.>''* ~~>S>PZ40 ^#V#~++ͫ~ ,‹#"> 2O !P~ ʋ">,‹#,‹#"B"@*B~#~,‹#*>ͽ*>">~#,j ‹*@*>}|ͬg͖+ڸ###Ѿ2=͖ :=ZK‹G !~#+<w#+++IW7!O~#+ +6.#HH!O~#~ &ûHT]+- : Qw#HS++NO SYM WITHIN 129 BYTES !~024*͖ښH~+ʙ-ʙ# d4>::7ʓ͊͊͏* Ú24* >24͊Q**" *#"~G!P~ʜO#~#~2=#~.*:= #"6#6p*~#+<7#z+){##~ #<*ͬ^#V#z< >;F#~T#<~#<+T]##~ #~#ON !M^#6 !M#~ ,Ha,{,_w,:O;,2426~~ n#~[#ͬ*"##6> 2O*+6I#6#6*|"6#6# ¢ S ABORT Y/N _Y ȷ ?;RESTORE REGISTERS POP H PUSH PSW ;SAVE RESPONSE LXI D,CRLF ;GET A CRLF CALL PRNMSG ;PRINT IT POP PSW ;RESTORE RESPONSE CPI 'Y' O Show current offset Oaddr Set offset for disassembly Ploaddr,hiaddr Prolog: ORG loaddr, EQU's for all syms now betw. lo - hi Q any command Quiet mode (no console out) Rname.type Read .COM, .DOC, .CTL, OR .SYM file Set offset before re"#" for decimal numbers: #99 Use "$" or "@" for curr P.C.: L$-20 Arithmetic may combine any of above, with "+" and "-": L.FOO-#20 bracketed operands ([,addr]) are optional carriage return means same as L Use =x to change it to another 1-letteR MVI A,'?' STA UFLAG ;SET USER FLAG STA FCB ;SET TO REPORT ALL USERS ENTIRES RET ; ; ; MODIFY COMMAND ; MDFY: LXI D,CONFRM ;GET CONFIRM MESSAGE CALL Dump symbol table Eaddr,.symbol Enter/replace symbol into table Eaddr,+ Enter sym as nearest lower + offset Faddr[,startaddr] Find 1st occurrence of addr F, Find next occurrence H Help with commands See also "-H" Hx Help with command "x"/)/ ???ASMCOMCTLSYMDOCa,{,_w,:O;,2426~~ n#~[#ͬ*"##6> 2O*+6I#6#6*|"6#6# ¢ S ABORT Y/N _Y ȷ ? name.CTL, name.DOC Uaddr Use addr for base of comments table X Purge all symbols and control Z Close .ASM file TL, OR .SYM file When saving .ASM, use "Lfrom,to" to list to disk, then "Z" to close the file. Sname.* Save name.SYM,ading a .COM Set "Uaddr" before reading a .DOC Rname.* Read name.SYM, name.CTL, name.DOC Sname.type Save .ASM, .DOC, .CTL, OR .SYM file When saving .ASM, use "Lfrom,to" to list to disk, then "Z" to close the file. Sname.* Save name.SYM,r command -H Delete help function (pick up about 2K bytes) -nn Back P.C. up nn =x Change C/R to mean "x" ? Show statistics . Sort symbol table / Slash redundant I/W from ctl ; Dump comments table ;addr,\comment\ Put in comment PRNMSG ;PRINT IT PUSH H ;SAVE REGISTERS PUSH B MVI C,CONIN CALL CPM ;GET CONFIRM CHARACTER CALL UCASE ;TO UPPER CASE POP B Iaddr,offset Increment every symbol from addr on, by "offset" K.symbol Kill symbol entry L[addr][,addr] List (Disassemble) L=nn Change default # lines in list M[addr][,addr] Make a DB then list (Disassemble) N No address comments toggle /)/ ???ASMCOMC#~ bG!e~# 7~7~~# G~ GGS Use ^S to stop/start help, C/R to quit A symbol is always preceeded by a ".": .BDOS A hex number has no "H": 5C All numbers default to hex. Use !91*!|1 bytes total tpa space. $ !|f bytes before overlaying the ccp. $ _ څ ||{0ontry C/ Del most recent ctl C-n[,addr] Back up most recent ctl by n optionally, Laddr CPloaddr,hiaddr,type,length[,type,length...] Enter a pattern of control entries D[addr][,addr] Dump memory D=nn Change default dump size DS[.symbol] ;addr, Delete comment ;;addr,\comment\ Enter lower case comment A[addr][,addr] Attempt to find DB/DW/INSTR B[addr][,addr] Build dflt syms C Dump ctl table Caddr Dump ctl from addr Caddr,type Add ctl entry (B,W,S,E,H,I) Caddr,K Kill ctl e ;YES FOR CONFIRM RNZ ;RETURN IF NOT ; PUSH H ;SAVE REGISTERS PUSH B LXI D,CKBUF ;SET CHECK DMA ADDRESS MVI C,SETDMA CALL CPM LXI B,8 ;FILE NAME LENGTH MVI A,' ' CALL CFILL ;CLEAR IT TO SPACES MVI B,8 ;NAME LENGTH LXI D,FNAME ;SET NAME ADDRESS LOOP3: MOV A,M ;MOVE NAME C,WRTBUF CALL CPM POP B POP H RET ;RETURN ; ; SEE IF WE HAVE A DRIVE SPECIFIER ; DRCHK: INX H ;BUMP ADDRESS MOV A,M ;IF SPECIFIER IN H,CKBUF LXI D,100H MVI C,VMSGND ;LENGTH TO END OF VERSION MESSAGE MDFY0: LDAX D ;GET CHARACTER CMP M ;DO THEY MATCH? JNZ MDFY1 ;DON'T ALLOW MODIFY IF NOFIER ; (INCLUDES LOWER CASE TO UPPER CASE TRANSLATION) ; FSET: MOV A,M ;GET FIRST CHARACTER CPI '*' ;WANT ALL? JNZ NOTAF ;SKIP OVER IF NOT INX H ;BUMP ADDGENERATED USING EDITOR AND OVERLAID WITH DDT ; MESSAGE STARTS AT ADDRESS MBUF ; HLPHND: LXI D,MBUF CALL PRNMSG ;PRINT HELP MESSAGE PUSH H PUSH B MVI C,CONIN CALL CPM D,INXFCB ;GET FCB ADDRESS MVI C,FOPEN ;OPEN FILE CALL CPM ;DO IT CPI 255 ;ERROR? JZ MDFY1 ;HOP OUT IF ERROR SUB A ;CLEAR A ASE ;TRANSLATE TO UPPER CASE DRVCHK1:SUI 'A' ;MAKE BINARY ADI 1 ;AND THEN TO ACTUAL NUMBER STA DSKSEL ;STROE DRIVE INX H ;BUMP ADDRESS PAST INX PUT, THIS IS IT DCX H ;RESTORE ADDRESS CPI ':' ;DRIVE SPECIFIER SEPARATOR? JNZ FSET ;GO HANDLE FILE NAME IF NOT MOV A,M ;GET DRIVE CODE CALL UCT INX H INX D DCR C ;MORE TO MATCH JNZ MDFY0 ;LOOP IF SO SUB A STA INXRC ;RESET TO FIRST RECORD LXI D,100H ;FIRST PART OF RESS DCR C ;DECREMENT COUNT JNZ CKPER ;CHECK FOR PERIOD IF MORE LEFT JMP DSKOK ;OTHERWISE GO DO DIRECTORY ; NOTAF: LXI D,FNAME ;SET FILENAME ADDRESS IN FCB MVI LXI D,CRLF JMP OPTERR ;DO CRLF AND RETURN ; ; Here for undefined or bad option ; PRNERR: LXI D,OPERR ;REPORT INVALID OPTION PRNMSG: PUSH H PUSH B ;SAVE REGISTERS OPTERR: MVI STA INXRC ;SET RECORD TO READ MVI C,FREAD LXI D,INXFCB ;READ FIRST RECORD CALL CPM ORA A ;ANY ERRORS JNZ MDFY1 ;HOP OUT IF SO LXI H ; DRIVE DESIGNATOR DCR C ;COUNT OFF TWO MORE CHARACTERS DCR C ; FOR DRIVE SPECIFIER JZ DSKOK ;DO DIRECTORY IF NO MORE LEFT ; ; SET UP FILE NAME SPECIF NOT POP B ;RESTORE REGISTERS POP H RET ; MDFY1: LXI D,MFERR ;GET MODIFY ERROR MESSAGE JMP OPTERR ;REPORT OPTION ERROR ; ; HELP COMMAND ; HELP MESSAGE IS FILE MVI C,SETDMA CALL CPM ;SET DATA ADDRESS LXI D,INXFCB MVI C,FWRITE ;WRITE FILE CALL CPM ORA A ;ERRORS? JNZ MDFY1 ;SKIP I"11e1MAST CAT á*-*/}|ڊ!"/*-{z|*+ v*/"/H*/"-!"/*+*-}>*/#"/ɯ22*!"-"/ < 0 NO MASTIN FILE$NAMES SUB INX D DCR C JZ DSKOK ;DO DIRECTORY IF OUT OF INPUT DCR B JNZ LOOP3 ;MOVE UP TO 8 CHARACTERS ; ; NEXT CHARACTER SHOULD BE '.' SEPARATOR ; CKPER: MOV A,M  ͳ ++AWAITING CARRIER x2x2x :y . ͳ ++TIMED OUT LOOKING FOR CARRIER ) :J ͳ ++CARRIER DETECTED Lͳ ++NO NUMBER WAS FOUND FOR DIALING++ !l\ 2|2h  >( BE 3 DIGITS$^!twd!}wx*++NO '-NAME.NNN' IN NAMES.SUB ++REISSUE: UCAT -NAME.NNN$h!twp!}w4(!4w#)4 xŒ*++TOO MANY IGNORE NAMES FOR TABLE$*++NO IGNORE NAMES IN MAST.CAT$*++EOF READING FNOT MVI A,'?' ;GET CP/M WILD CHARACTER CALL CFILL ;FILL REST WITH ? QFILL1: INX H ;BUMP INPUT ADDRESS DCR C ;ANY CHARACTERS LEFT JZ DSKOK ;DO! *MAST.CAT HAS ENTRIES.$ %> >   ~ [_#K> XXXXXXXX.YYY, . XXXXXXXX.YYY,XXXXXXXX.YYY;ZXXXXXXXX.YYY,XXXXXXXX.YYY;Z$$$ .SUB)"1s**}|\!"*{zN*H*"*"!"**}>*#"ɯ22!""<ª 0 NO NAMES FILE$NEW CAT 0 NO M,N Y**}|I!"*{z;* ~# ADEOQRSTVn OL  U 0 2 ͳ MULTIPLE ERRO ͳ : INVALID OPTION ON MODEM COMMAND - PRESS RETURN FOR HELP, CTL-C IF NOT ͳ Format for command is: MODEM # FILENAME Where # is a 1 C >) _>  > OL  U 0 2 ͳ MULTIPLE ERRORS ENCOUNTERED. TYPE Q TO QUIT, R TO RETRY: 7   _RQZ ~  #ô ͳ PRESS RETURN TO CONTINUE 7    *]OR IGNORE NAMES. MAY BE MISSING ) AFTER LAST NAME.$4 4Jͅ:e[:fŠ:gG:y[yp!̀Äg!̀ڻ !t̀ʩ!wJ!BJDEL: $g!w!gBMADD: $g!wG!g56.#56 DIRECTORY IF NOT MOV A,M ;GET NEXT CHARACTER CPI '.' ;PERIOD SEPARATOR? JZ CKPER ;HOP OUT IF SO JMP QFILL1 ;LOOP IF NOT STCHR: STAX D INX H 5 x2e!  05 :5 0DM)) )o. ${h ++INVALID BAUD RATE++$ͳ Number to dial: _ 7 ʁ z  e  e  xͳ Dialing...x _ ʤ  O y:ҟ 0ڟ O ß y  Gy2 y2   x .- *" &0 DISK FULL: MASTOUT$!"**#"ɯ22!"!"<£ 0 NO DIR SPACE: MASTOUT$MAST BAK CAT 0 g!̀:g-b:^-&:f *++SERIAL MUSTINTO FCB CALL UCASE ;FORCE UPPER CASE CASEOK: CPI '.' ;PERIOD? JZ CKPER ;HOP OUT IF SEPARATOR CPI '*' ;NON-LEADING WILD CARD? JNZ STCHR ;SKIP IF 2f!~ >0 >   ~ [_#K> _> _w#w#€>*}›"><  CANNOT CLOSE MASTOUT$ w# ! ,!6;#5!g ,~ -) #:ex >.p;p pxw#52e6 #p6#x>2e!͡6,#͡:;424ͯ6.#ͯ:f4 ʸ,.; w#¯422f6 #26# ;GET CHARACTER CPI '.' ;PERIOD? JNZ ERROR ;ERROR IF NOT INX H ;BUMP ADDRESS DCR C ;MORE INPUT? JZ DSKOK ;GO DO DIRECTORY IVE IT LXI D,TBUF ;GET DMA ADDRESS MVI C,SETDMA CALL CPM ;SET DMA ADDRESS MVI C,RTNCUR CALL CPM ;GET CURRENT DISK NUMBER STA OLDDSK ;SAVE Il LP0: MVI A,-4 AND 0FFH ;NO SPEARATOR FOR LAST COLUMN LP1: ADD H ;Add 1 col of chars CMP B ;SCREEN FULL? JNC LP2 ;Loop if not INR L ;BUMP COUNT CALL UCASE ;FORCE UPPER CASE CASOK1: CPI '*' ;NON-LEADING WILD CARD? JNZ STFTP ;GO STORE FILE TYPE CHARACTER IF NOT MVI A,'?' CALL CFILL ;FILL REST WITH QUESTICOUNT OFF ONE JZ STHADR ;FULL MODIFY IF 1 COLUMN DAD D DCR A JZ STHADR DAD D STHADR: XCHG ;MODIFICATION TO DE LHLD HDRADR ;GET HEADER ADDRE B,A ;SAVE IT IN B CPI 60 ;SMALL SCREEN? JNC LP02 ;SKIP IF NOT LHLD CRLF ;GET CRLF SHLD CRPOS ;SPLIT BOTTOM MESSAGE LP02: LXI H,1000H F NOT ; ; CHECK FILE TYPE ; MOV A,M CPI '*' ;WANT ALL OF THEM? JZ DSKOK ;TO DIRECTORY IF SO LXI D,FTYPE ;"TYPE" ADDRESS IN FCB MVI B,3 ;FIL A MOV A,L ;NUMBER OF COLUMNS TO A LXI H,22 ;START WITH FULL OFFSET JZ CKBRF ;SKIP IF BRIEF MODE LXI D,-11 ;OFFSET FOR FULL MODE CPI 3 JMP LP1 ;CHECK FOR ANOTHER COLUMN ; LP2: MVI H,0 SHLD NCOLS ;Store # columns ; LXI D,-7 ;OFFSET FOR BRIEF MODE LDA SFLAG ;GET BRIEF FLAG ORA ON MARK JMP DSKOK ;IGNORE ANY EXTRA INPUT STFTP: STAX D INX H INX D DCR C JZ DSKOK ;TO DIRECTORY IF NO MORE INPUT DCR B JNZ LOOP5 SS DAD D ;CENTER FOR NARROW SCREEN SHLD HDRADR ;STORE NEW START ; ; SET ADDRESSES, AND SELECT DISK IF NECESSARY ; NOWMD: LXI H,MBUF ;BUFFER ADDRESS SHLD BUFADR ;SA ;H=16 chars/col ;L=column counter LDA SFLAG ;Report file size? ORA A JZ LP0 ;If yes then MVI H,22 ; 22 chars/coE TYPE LENGTH MVI A,' ' ;CLEAR FILE TYPE CALL CFILL ;TO SPACES LXI D,FTYPE ;TYPE ADDRESS IN FCB MVI B,3 ;TYPE LENGTH LOOP5: MOV A,M ;GET CHARACTER ;LESS THAN THREE? JNC NOWMD ;SKIP IF NOT JMP STOFST ;GO SET OFFSET CKBRF: CPI 4 ;2 COLUMNS? JNC NOWMD ;DON'T MODIFY FOR BRIEF MODE STOFST: DCR A ; USE SEARCH FOR FIRST AND SEARCH FOR NEXT SO THAT ; IT WILL WORK ON ANY SYSTEM ; ; First, set display size (S option can change it) ; (needs better coding) ; DSKOK: LDA SCSIZE ;GET SCREEN SIZE MOVJMP DSKOK ;IGNORE ANY EXTRA INPUT ; ; ERROR HANDLING - DISPLAY ERROR MESSAGE AND RETURN ; ERROR: LXI D,ERMSG MVI C,WRTBUF CALL CPM JMP CPMRET ; ; FCB IS SET UP, NOW DO DIRECTORY ; T LDA RFLAG ;SYSTEM RESET WANTED? ORA A JZ DSKOK1 ;SKIP IF NOT MVI C,SREST CALL CPM ;RESET DISK SYSTEM (MAKES A CURRENT) DSKOK1: LDA DSKSEL ;WANT RDDON: LDA TTFLAG ;WANT DISK NAME FOR TITLE? ORA A JZ RDON1 ;SKIP IF NOT LXI H,FNAME MVI M,'-' ;FIRST CHARACTER = DASH MVI B,10 XCHG ;BUFFER ADDRESS TO HL LDA USRNO ;GET USER NUMBER CMP M ;SAME AS THIS ONE? XCHG RNZ ;RETURN IF NOT FMOV0: LDA SYFLAG ;WANT SYSTEM FILES? ORA MVI C,SLDISK CALL CPM ;SELECT DISK ; ; NOW READ DIRECTORY ; NOSEL: LXI D,FCB ;SET FCB ADDRESS MVI C,SCHFRST CALL CPM CPI 0FFH ;IS THERE A FIRST ENTRY? IP IF PAST FILE NAME ANI 7FH ;STRIP PARITY FROM NAME FLOOP1: STAX D INX H INX D DCR C JNZ FLOOP ;LOOP UNTIL DONE XCHG ;BUFFER ADDRESS BACTO PROPER ; PLACE IN BUFFER ; FMOVE: ANI 3 ;LOW TWO BITS ONLY ADD A ;MULTIPLY A*32 ADD A ADD A ADD A ADD A ADI 80H ;ADD DMA A DIFFERENT DISK ORA A JNZ SELCT ;SKIP IF SO LDA RFLAG ;DID WE RESET SYSTEM? ORA A JZ NOSEL LDA OLDDSK ;GET OLD DISK ORA A ;SET FLAGS RM ;SYSTEM FILE IF MSB SET FMOV1: LHLD BUFADR ;GET BUFFER START MVI M,0 ;CLEAR FIRST BYTE INX H INX D ;POINT TO FIRST BYTE OF NAMEA ;SET FLAGS JNZ FMOV1 ;MOVE ALL IF SO LXI H,10 ;GET OFFSET TO T2 DAD D ;ADD BUFFER POSITION MOV A,M ;GET CHARACTER ORA A JZ RDDON ;GO REPORT NO FILES IF NOT CALL FMOVE ;MOVE ENTRY TO PROPER PLACE ; ; NOW USE SEARCH FOR NEXT ; LOOP6: JNZ LOOP60 ;DON'T BUMP ADDRESS IF NO STORAGE LHLD BUFADR K TO HL MVI M,0 ;CLEAR BYTE AFTER R.C. LHLD NUMBER ;FIRST BUMP COUNT INX H SHLD NUMBER RET ; ; ; DIRECTORY READ DONE ; NOW, SET DISK PARAMETERS AND DISK SIZE ;START MOV E,A ;TO E REGISTER MVI D,0 ;CLEAR D REG LDA UFLAG ;USER CODE SPECIFIED ORA A ;SKIP IF NOT JZ FMOV0 XCHG ;WAS IT A? JZ NOSEL ;EVERYTHING'S COOL IF SO INR A ;BUMP IT FOR RESELECT SELCT: DCR A ;TO PROPER FORM FOR CP/M MOV E,A ;INTO REGISTER E FOR CP/M CALL XCHG ;HL=SOURCE, DE=DESTINATION MVI C,15 ;MOVE 15 BYTES (REST DON'T MATTER) MVI B,11 ;FILE NAME LENGTH FLOOP: MOV A,M DCR B JM FLOOP1 ;SK 0FFH ;ANYTHING FOUND? JZ RDDON ;GO REPORT RESULTS IF NOT CALL FMOVE ;MOVE ENTRY TO PROPER PLACE JMP LOOP6 ;LOOP UNTIL SEARCH FAILS ; ; ROUTINE TO MOVE DIRECTORY ENTRY LXI D,32 ;DIRECTORY ENTYR SIZE DAD D ;BUMP ADDRESS SHLD BUFADR ;SAVE NEW ADDRESS LOOP60: LXI D,FCB ;FCB ADDRESS MVI C,SCHNEXT CALL CPM CPI ;ADDRESS TO DE INX D ;BUMP ADDRESS TO NEXT POSITION MVI A,'?' ;GET A QUESTION MARK CALL CFILL ;FILL WITH QUESTION MARKS MVI B,20 ;ZERO OUT THE REST SETDON ; AND HOP OUT WHEN REACHED DCX H ;COUNT DOWN 1 PUSH H ;SAVE COUNT LHLD BUFADR ;GET BUFFER ADDRESS LXI D,14 ;OFFSET TO S0 DAD ;FETCH IT INX H ;POINT TO BLOCK COUNT MOV E,M ;TO E REGISTER MVI D,0 ;SINGLE BYTE, SO CLEAR D MVI A,0 ;EXTENT MASK = 0 FOR 1.4 ; ; NOW SET ADD A ADD A ADI 2 ;PLUS 2 TO SKIP FIRST BYTE ADI 80H ;ADD START ADDRESS MOV L,A MVI H,0 SHLD TTLADR ;SAVE ADDRESS JMP RDON1 K PER BLOCK RAR ;SHIFT IT ORA A ;RESET FLAGS JZ SZ3 DAD H ;TIMES 2 JMP SZ2 ;LOOP UNTIL SIZE = 0 SZ3: SHLD DSKSZ ;SAVEO DE REGISTERS INX H MOV D,M JMP SZE ;GO SIZE DISK ; ; HERE FOR VERSION 1.4, GET PARAMETERS FROM BDOS INTERNALS ; VERS14: LHLD BOOT ;GET BOOT ADDRESS MVI L,0 SUB A ;SET A = 0 CALL CFILL ;CLEAR REST TO ZERO LXI D,FCB ;GET FCB ADDRESS STAX D ;FORCE FIRST BYTE TO ZERO MVI C,SCHFRST ;SEARCH FOR FIRST IT MVI C,3 ;SECTORS (SHIFT FACTOR) PER 1K SZ1: ORA A ;CLEAR CARRY RAR ;SHIFT RIGHT DCR C ;THREE TIMES (DIVIDE BY 8) JNZ SZ1 STA DISK SIZE ; SZE: STA EXTMSK ;SAVE EXTENT MASK MOV A,B ;GET BSF STA BLKSHF ;SAVE IT INR C ;SECTORS/BLOCK MOV A,C STA BLKREC ;SAVE ;AND SKIP CLRTTF: SUB A ;CLEAR A STA TTFLAG ;CLEAR TTFLAG ; RDON1: MVI C,GETVERS ;WHICH VERSION CP/M? CALL CPM MOV A,L ;VERSION CODE TO A ORA DISK SIZE LXI H,MBUF ;BUFFER START SHLD BUFADR ;TO LOCAL STORAGE LHLD NUMBER ;GET COUNT SETUP: MOV A,L ;TEST COUNT ORA H ; FOR ZERO JZ ;CLEAR LOW BYTE LXI D,-0D00H ;OFFSET DOWN TO BDOS DAD D MVI L,3CH ;POINT TO BSF MOV B,M ;BSF TO B INX H ;BUMP UP TO BSM MOV C,M CALL CPM CPI 255 ;FIND IT? JZ CLRTTF ;CLEAR TT FLAG IF NOT ANI 3 ;CLEAR TOP BITS ADD A ;FIND POSITION ADD A ADD A BLKSZ ;SAVE BLOCK SIZE (IN K) XCHG ;CLOCK COUNT TO HL INX H ;TRUE BLOCK COUNT SHLD BLKS ;SAVE IT ; ; NOW CONVERT TO K ; SZ2: ORA A ;A = T FACTOR TO B INX H MOV C,M ;BSM IN C-REGISTER INX H MOV A,M ;EXTENT MASK TO A INX H ;DSM NEXT (NUMBER OF BLOCKS - 1) MOV E,M ;TA JZ VERS14 ;SKIP IF 1.4 MVI C,GETADR ;GET DISK PARAMETER CALL CPM ; BLOCK ADDRESS INX H INX H ;BUMP UP TO BSF MOV B,M ;SHIF D ;AT S0 MVI M,0 ;S2 = 0 DCX H MVI M,0 ;S1 = 0 DCX H ;AT EXTENT BYTE MOV A,M ;TO A REG ORA A ;BAS LXI B,12 ;OFFSET TO EXTENT DAD B ;POINT TO EXTENT BYTE ANA M ;MULTIPLE EXTENTS IN DIRECTORY? JZ MULTP22 ;SKIP IF NOT LXI B,80H ;EXTEESS LHLD TEMP ;GET COUNT MOV A,L ORA H ;DONE? JZ MULTPL9 ;HOP OUT IF NO MORE DCX H ;COUNT DOWN ONE SHLD TEMP ;SAVE COUNT LDA EXTMSK ;GET EXTENT MASK SUB C ;IS IT REALLY MULTIPLE? JC MULTPL4 ;HOP OVER IF SO ; ; MULTIPLE EXTENT IN BASE DIRECTORY ENTRY ; LXI D,80H ;EXTENT SIZE SUB D ;SUBTRACT THIS EXTENT JC MULTPL7 ;HOP OUT IF NOT BASE ; POP D ;RESTORE MBUF ADDRESS LXI H,15 ;OFFSET TO RECORD COUNT DAD D MOV LHLD BUFADR ;RECALL ADDRESS LXI D,12 DAD D ;POINT TO EXTENT MVI M,0 ;SHOW AS BASE EXTENT RET ;AND THAT'S ALL ; ; TRUE MULTIPLE EXTENTE EXTENT? CNZ MULTPL ;GET MULTIPLE EXTENTS SETUP2: LHLD BUFADR ;GET BUFFER ADDRESS LXI D,32 ;ENTRY LENGTH DAD D ;POINT TO NEXT ENTRY SHLD BUFADR ;SAVNE CHARACTER CMP M JNZ MULTPL7 ;HOP OUT IF DIFFERENT INX H ;BUMP ADDRESSES INX D DCR C JNZ MULTPL6 ;CHECK NEXT CHARACTER IF NOT DONE POP POP H ;RECALL FCB ADDRESS MVI C,12 ;NUMBER OF BYTES TO COMPARE PUSH H ;SAVE ADDRESSES PUSH D ;MBUF ADDRESS LAST MULTPL6:LDAX D ;CHECK O LXI H,0 ;CLEAR HL MULTPL1:DAD D ;ADD 80H FOR EACH FULL EXTENT DCR C JNZ MULTPL1 XCHG ;RESULT TO DE LHLD BUFADR ;GET BUFFER ADDRESS LXI E,M ;PUT BASE RECORD COUNT IN DE INX H MOV D,M XTHL ;GET THIS ADDRESS, SAVE BASE ADDRESS LDA EXTMSK ;GET EXTENT MASK PUSH H ;SAVE ADDRESS ; MULTPL4:LXI D,MBUF ;GET MEMORY BUFFER START LHLD NUMBER ;GET NUMBER SHLD TEMP ;SAVE IT LHLD BUFADR ;GET THIS FCB ADDRESS MULTPL5:PUSH H ;SAVE THIS FCB ADDRE NEW ADDRESS POP H ;RESTORE COUNT JMP SETUP ;GO DO NEXT ENTRY ; ; ROUTINE TO HANDLE MULTIPLE EXTENTS ; BUFADR = FCB ADDRESS IN MBUF ; MULTPL: MOV C,A ;EXTENT TO C D ;POSSIBLE MATCH, CHECK PUSH D ; IF BASE EXTENT LXI H,12 ;OFFSET TO EXTENT DAD D MOV D,M ;GET EXTENT LDA EXTMSK ;GET EXTENT MASK XCHG ;PARTIAL RESULT TO HL DAD B ;ADD REMAINING EXTENT XCHG ;SET HL=ADDRESS, DE=VALUE MOV M,D ;STORE RECORD COUNT DCX H MOV M,E B,15 ;OFFSET TO R.C. DAD B ;POINT TO R.C. MOV C,M ;R.C. TO C INX H ;GET BOTH BYTES IN CASE WE MOV B,M ;HAVE ALREADY ADDED SOMETHING NT SIZE LXI H,0 ;CLEAR PARTIAL RESULT MULTP21:DAD B ;ADD EXTENT SIZE DCR A ;COUNT OFF EXTENTS JNZ MULTP21 DAD D ;ADD TO PARTIAL COUNT XC ;COUNT DOWN ONE FOR LIMIT MOV A,L ;SINGLE ENTRY? ORA H JZ SRTDON ;DON'T NEED TO SORT 1 ENTRY SHLD TEMP ;SAVE LIMIT SHLD TEMP2 ; IN TWO PLACD EXTCNT ;SAVE UNMODIFIED FOR DISPLAY DAD D ;SUBTRACT MULTIPLES SHLD NUMBER ;SAVE NEW COUNT SHLD TEMP ;SAVE AS LOOP COUNTER LHLD INDEX ;GET INDEX ADDREVE HIGH BYTE DCX H MOV M,E LHLD BUFADR ;GET MULTIPLE ADDRESS AGAIN MVI M,1 ;FLAG AS MULTIPLE EXTENT LHLD MLTPLS ;GET MULTIPLE COUNT DCX H SHL ; IN INDEX ARRAY MOV M,D INX H INDX2: XCHG ;MBUF POINTER TO HL DAD B ;POINT TO NEXT ENTRY XCHG ;RESTORE PROPER ORDER JMP INDX IES DAD H ;TIMES ENTRY LENGTH (32) DAD H DAD H DAD H DAD H LXI D,64 ;PLUS A LITTLE EXTRA DAD D LXI D,MBUF ;ADD TO BUFFHG ;RESULT BACK TO DE MULTP22:POP H ;RESTORE ADDRESS LXI B,15 ;OFFSET TO R.C DAD B MOV C,M ;GET LOW BYTE MVI B,0 ;80H IS MAX FOR ON ORA A ;MULTIPLE EXTENT? JNZ INDX2 ;DON'T COUNT MULTIPLES PUSH H ;SAVE ADDRESS LHLD TEMP ;GET COUNT MOV A,L ;SEE IF DONE ORASS LXI B,32 ;ENTRY LENGTH LXI D,MBUF+1 ;POINT TO FIRST CHARACTER INDX: DCX D ;AT FIRST BYTE LDAX D ;GET FIRST BYTE INX D ;RESTORE ADDRESS D MLTPLS ;SAVE IT RET ;AND RETURN ; MULTPL7:POP D ;RESTORE MBUF ADDRESS LXI H,32 DAD D ;AT NEXT ENTRY POP D ;RESTORE THIS ADDRES ;LOOP FOR NEXT ENTRY ; ; SORT ROUTINE STARTS HERE ; SORT: LHLD NUMBER ;GET COUNT MOV A,L ORA H ;ANYTHING TO SORT? JZ SRTDON ;HOP OUT IF NOT DCX H ER START DAD D SHLD INDEX ;SAVE START OF INDEX ARRAY LHLD MLTPLS ;GET NUMBER OF MULTIPLES (-) XCHG ;TO DE LHLD NUMBER ;GET NUMBER OF FILES SHLE ENTRY XCHG ;BASE COUNT TO HL DAD B ;ADD THIS ONE POP D ;GET BASE R.C. ADDRESS XCHG ;VALUE TO DE, ADDR TO HL MOV M,D ;SA H DCX H SHLD TEMP ;STORE NEW COUNT POP H ;RESTORE INDEX ADDRESS JZ SORT ;GO SORT IF DONE ; MOV M,E ;STORE ADDRESS INX H MVI M,'*' POP H ;RESET STACK RET ;AND RETURN ; ; SETUP DONE, DO SORT ; (USE INDEX ARRAY TO POINT TO DESIRED VALUES) ; SETDON: LHLD NUMBER ;GET NUMBER OF ENTRS XCHG ;SWAP ORDER JMP MULTPL5 ;CHECK NEXT ENTRY ; MULTPL9:LHLD BUFADR ;NO MATCH IF HERE, FLAG LXI D,12 ; ERROR (EXTENT WITH DAD D ; NO BASE)ES SORT0: LHLD INDEX ;GET INDEX POINTER SHLD TEMP1 ;SAVE IT LOCALLY SUB A STA SWAP ;SHOW NO SWAP DONE SORT1: LHLD TEMP1 ;MAIN LOOP - GET INDEX VALUE MOV E MVI M,' ' INX H INX H ;SKIP OVER RECORD COUNT INX H MVI M,'K' ;STORE "K" INDICATOR SPC3: POP H ;RESTORE ADDRESS DAD D ;ADD OFT LOOP COUNTER SHLD TEMP2 ;SAVE LIMIT FOR NEXT PASS JNZ SORT0 ;SORT SOME MORE IF NOT DONE ; ; SORT DONE, INDEX ARRAY NOW HAS ADDRESS OF FIRST ; CHARACTER IN EACH DIRECTORY ENTRY, IN ALPHA SEQUENCE ;TEST MORE IF EQUAL JNC SORT4 ;SKIP IF NO SWAP NEEDED LHLD TEMP1 ;GET INDEX POINTER MOV E,M ;POINTER TO DE INX H MOV D,M DCX H SHLD TEMP ;STORE NEW COUNT POP H ;RESTORE ADDRESS JZ CNVNBR ;GO CONVERT NUMBERS IF NONE LEFT PUSH H ;SAVE ADDRESS MOV A,M ;GET EXTENT BYTE UNT OFF ONE DONE SHLD TEMP ;STORE NEW COUNT MOV A,L ORA H ;DONE WITH LOOP? JNZ SORT1 ;CONTINUE IF NOT LDA SWAP ;ANYTHING SWAPPED? ORA ,M ;MOVE POINTER TO DE INX H MOV D,M INX H SHLD TEMP1 ;STORE UPDATED POINTER MOV A,M ;GET POINTER TO NEXT WORD INX H MOV H,M 12 ;POINT TO EXTENT BYTE LXI D,32 ;OFFSET TO NEXT SPCLOOP:PUSH H ;SAVE ADDRESS MOV A,M ;GET EXTENT BYTE CPI '*' ;ERROR FLAG? JZ SPC1 . ; SRTDON: LXI H,0 SHLD USED ;INITIALIZE "USED" COUNTER ; ; NOW CONVERT EXTENT BYTE TO SPACE ; LHLD NUMBER ;GET NUMBER OF ENTRIES SHLD TEMP ;SAVE IT LXI H,MBUF+ ;BACK UP TO X(I) DCX H MOV B,M ;GET OLD POINTER MOV M,D ;SWAP ONE BYTE DCX H MOV C,M MOV M,E ;LOW POINTER SWAPPED INX H CPI '*' ;ERROR FLAG? JZ SPC2 ;DON'T CLEAR ERROR FLAG MVI M,' ' ;MAKE IT A SPACE SPC2: INX H ;CLEAR NEXT TWO BYTES MVI M,' ' INX H A JZ SRTDON ;DONE SORTING IF NOT LHLD TEMP2 ;GET OLD LIMIT DCX H ;MAKE IT 1 LESS MOV A,L ORA H ;ANY LEFT SHLD TEMP ;RESE MOV L,A XCHG ; = X(I+1), = X(I) MVI C,11 ;NUMBER OF CHARACTERS TO COMPARE SORT2: LDAX D ;GET X(I+1) SUB M ;X(I+1) - X(I) JZ SORT3;SKIP IF SO ORA A ;BASE EXTENT? JNZ SPC3 ;DON'T BOTHER WITH IT IF NOT SPC1: LHLD TEMP ;GET COUNT MOV A,L ORA H ;ANY LEFT? DCX H INX D ;BUMP ADDRESSES INX H DCR C ;MORE CHARACTERS TO COMPARE? JNZ SORT2 ;LOOP IF SO SORT4: LHLD TEMP ;GET LIMIT FOR LOOP DCX H ;CO ;GET BACK UP TO X(I+1) POINTER INX H MOV M,C ;FINISH SWAP INX H MOV M,B STA SWAP ;SHOW A SWAP JMP SORT4 ;HOP OUT OF INNER LOOP SORT3: FSET TO NEXT ENTRY JMP SPCLOOP ;DO NEXT ENTRY ; ; CONVERT RECORD COUNT TO ASCII ; CNVNBR: LHLD NUMBER ;GET COUNT SHLD TEMP ;SAVE FOR LOOP CONTROL LXI H,MBUF+15 ;GET R.C. A B ;SUBTRACT UNTIL OVERFLOW JNC CNVRT2 ; NO CARRY = OVERFLOW INR A ;BUMP NUMBER JMP CNVRT1 ; CNVRT2: CPI '0' ;ZERO? JNZ CNVRT3 LDA SWA JMP CNV3 ; ; ADD FILE SIZE TO "USED" ; CNV4: PUSH H ;SAVE STORAGE ADDRESS LHLD USED DAD D ;ADD THIS FILE SHLD USED POP H ;RESTORE STORAGE DCX H SHLD TEMP ;SAVE NEW COUNT LHLD TEMP1 ;GET R.C. ADDRESS MOV E,M ;LOW BYTE TO E MVI M,' ' ;PUT IN A SPACE INX H ;AT HIGH BYTE INX D ;BUMP ADDRESS LXI B,-10 CALL CNVRT INX D LXI B,-1 CALL CNVRT LDA SWAP ;CHECK FOR ZERO ORA A ;ANYTHING CONVERT A ;MINUS 1 ANA B ;TEST LOW COUNT BYTE JZ CNV21 ;HOP OVER IF ZERO INX D ;BUMP 1 BLOCK IF NOT EVEN NUMBER CNV21: LDA BLKSZ ;GET BLOCK SIZE CNV3: ODDRESS SHLD TEMP1 ;SAVE IT CNV1: LHLD TEMP1 ;GET MBUF ADDRESS LXI D,-15 ;OFFSET BACK TO START DAD D ;POINT AT START MOV A,M ;GET FIRST BYTE ;LOOP FOR NEXT ENTRY ; ; BINARY TO ASCII CONVERSION, 4 DIGITS ; WITH LEADING ZERO SUPPRESSION ; ; HL = STORAGE ADDRESS, DE = NUMBER TO CONVERT ; CNVIT: XCHG ;SWAP ORDER (DE = ADDR, HL = NUMBER) SUB ADDRESS CALL CNVIT ;CONVERT IT CNV5: LHLD TEMP1 ;GET POINTER LXI D,32 DAD D ;POINT TO NEXT ENTRY SHLD TEMP1 ;STORE NEW COUNT JMP CNV1 MOV D,M ;COUNT IN DE MVI M,' ' ;COUNT AREA = SPACES NOW DCX H DCX H ;BACK UP TO STORAGE ADDRESS DCX H ; ; CONVERT RECORD COUNT TO K ; IN INTEED? RNZ ;RETURN IF SO MVI A,'0' STAX D ;STORE AT LEAST 1 ZERO RET ; ; ROUTINE WHICH DOES THE CONVERSION ; CNVRT: MVI A,'0' ;GET BASE NUMBER CNVRT1: DAD RA A ;CLEAR CARRY RAR ;DIVIDE BY 2 ORA A ;SET FLAGS JZ CNV4 ;IN K IF ZERO XCHG DAD H XCHG ;TIMES 2 IF NOT ORA A ;MULTIPLE EXTENT? JNZ CNV5 ;IGNORE MULTIPLE EXTENTS LHLD TEMP ;GET COUNT MOV A,L ORA H JZ CNVDON ;HOP OUT IF NO MORE LEFT A STA SWAP ;SHOW NO LEADING DIGITS LXI B,-1000 ;CONVERT 1000'S DIGIT CALL CNVRT INX D ;BUMP ADDRESS LXI B,-100 ;100'S DIGIT CALL CNVRT MOV D,A ;SHIFT RIGHT 3 TIMES MOV A,E RAR MOV E,A DCR C JNZ CNV2 ; ; CHECK FOR PARTIAL RECORD ; LDA BLKREC ;RECORDS PER BLOCK DCR GRAL NUMBER OF BLOCKS ; LDA BLKSHF ;BLOCK SHIFT FACTOR MOV C,A ;TO C REGISTER MOV B,E ;LOW BYTE TO B CNV2: ORA A ;CLEAR CARRY MOV A,D RAR P ;LEADING ZERO ORA A JZ CNVRT4 ;HOP OVER IF SO MVI A,'0' ;RESTORE ZERO IF NOT CNVRT3: STAX D STA SWAP ;SHOW LEADING DIGIT ; ; CORRECT FROM OVERFLOW LLOC6: MOV A,H ;FORM NEGATIVE CMA MOV H,A MOV A,L CMA MOV L,A INX H XCHG ;NEGATIVE OF USED TO DE LHLD DSKSZ ;GET DISK SI LHLD BLKS ;GET NUMBER OF BLOCKS DCX H ;-1 MVI C,3 ALLC0: ORA A ;CLEAR CARRY MOV A,H RAR MOV H,A ;DIVIDE BY 8 MOV ONVERT TO ASCII LHLD USED ;GET "K" USED LXI D,ASCUSE ;GET ADDRESS XCHG CALL CNVIT ; ; SET DRIVE IDENTIFIER ; LDA TFLAG ;DID WE INPUT A TITLE ORA A ;BUMP TO NEXT POP B ;RESTORE COUNT DCX B ;COUNT OFF ONE BYTE MOV B,A ORA C ;MORE BYTES TO DO? JNZ ALLOC1 ;GO DO NEXT BYTE ; ; CONVDA OLDDSK ;GET DEFAULT DISK INR A ;BECAUSE OF HOW DSKSEL IS STORED CNVD1: DCR A ;FORM TRUE DISK CODE ADI 'A' ;ADD BIAS STA ASCDSK ;STORE DISK CODE ;; CNVRT4: MOV A,B CMA MOV B,A MOV A,C CMA MOV C,A INX B DAD B RET ; ; CONVERT NUMBER OF FILES "USED" ; CNVDON: LHLD NUMBER ;GET NUMBER ALLOC1: PUSH B ;SAVE COUNT LDAX D ;GET VECTOR BYTE PUSH D ;SAVE ADDRESS MVI E,8 ;BITS PER BYTE LXI B,1 ALLOC2: RAL ;BLOCK IN U A,L RAR MOV L,A DCR C JNZ ALLC0 INX H ;+1=ALLOCATION VECTOR SIZE MOV B,H MOV C,L ;TO BC REGISTER LXI H,0 ;CLEAR COUNT JNZ ALLOC ;SKIP DRIVE SET IF SO LDA TTFLAG ;DO WE HAVE DISK NAME FOR TITLE? ORA A JZ CNVD0 ;SKIP IF NOT LXI D,ASCTTL ;TITLE GOES HERE LHLD TTLERT USED (IN HL IN BLOCKS) TO K ; LDA BLKSZ ;GET BLOCK SIZE ALLOC5: ORA A ;CLEAR CARRY RAR ORA A ;ZERO YET? JZ ALLOC6 DAD H JMP ALLOC5 A ; DETERMINE FREE SPACE ON DISK FROM ALLOCATION VECTOR ; ALLOC: MVI C,GETALLC ;GET ALLOCATION VECTOR CALL CPM MOV E,A ;TO DE REGISTER MOV D,B ;(MAINTAINING 1.4 COMPATIBILITY) LXI D,ASCNUM XCHG ;SWAP ORDER CALL CNVIT ;CONVERT IT LHLD EXTCNT ;GET EXTENTS LXI D,ASCEXT ;PUT IT HERE XCHG CALL CNVIT ;CSE? JNC ALLOC3 ;SKIP IF NOT DAD B ;ADD 1 MORE BLOCK USED ALLOC3: DCR E JNZ ALLOC2 ;LOOP FOR 8 BITS POP D ;RESTORE ADDRESS INX D I A,' ' CALL CFILL ;FILL REST WITH SPACES JMP ALLOC ;THEN REPORT RESULTS CNVD0: LDA DSKSEL ;DID WE SELECT A DISK? ORA A JNZ CNVD1 ;HOP OVER IF SO LADR ;GET ADDRESS MVI C,10 ;LENGTH OF TITLE MVTTL: MOV A,M ;GET CHARACTER STAX D INX H INX D DCR C JNZ MVTTL MVI B,10 MVZE DAD D ;FORM "LEFT" LXI D,FREE ;GET STORAGE AREA XCHG ;SET PROPER ORDER (HL=ADDR, DE=NUMB) CALL CNVIT ;CONVERT TO ASCII ; ; NOW DO PRINT, FIRST DO ;Col done > part col? JNC COLFUL DCX H ;If yes-one less line COLFUL: DAD H ;Times 2 bytes/entry DAD D ; And point to it PUSH H ;Save new ;Count off 1 entry SHLD NUMBER XCHG ;Address to HL MVI B,8 ;8 chars in file name CALL WRTMSG ;Print a file name PUSH H ;Save address ;Save for later XCHG ;To DE LHLD NUMBER ;Get # entries XRA A SUB E ;Make negative MOV E,A DCR D LXI B,0 ;Re ; Else restore stack LXI D,COLSEP ;And print separator CALL TYPE POP H ;Get pointer XCHG ;Pointer to DE POP H ;Get # of lines H ;Save for later INX H ;Bump to next pointer INX H SHLD INDEX ;Store for next line DCX H ;Back to this item DCX H NXTONE: MOV E,M HEADER ; LDA FFLAG ;WANT FORM FEED FIRST ORA A JZ PHEAD ;SKIP IF NOT LXI D,FFMSG CALL TYPE ;DO A FORM FEED ; PHEAD: LHLD HDRADR ;GET HEADER ADDR B,9 ;Yes, type+siz=9 chrs SIZNO: CALL WRTMSG ;Print type (size) LHLD NCOLS ;Get # of columns to do LDA TEMP1 ;Get # columns done INR A ;Bump it CALL PSPACE ;Print a space POP H ;Restore address MVI B,3 ;3 chars in file type LDA SFLAG ;Report size ? ORA A JZ SIZNO MVIset # lines DVD1: DAD D ;Subtract NCOLS JNC DVD2 INX B ;Bump # lines JMP DVD1 ; Until done DVD2: POP D ;Get # columns DAD D MOV PUSH H ;Resave it LDA TEMP1 ;Get # columns done MOV C,A LDA TEMP ;Get # partial columns ORA A JZ COLFUL ;Skip if none CMP C ;Pointer to DE INX H MOV D,M LHLD NUMBER ;Get number to print MOV A,L ;See if any left ORA H JZ PRTDON ;Hop out if not DCX H ESS XCHG ;TO DE REGISTER CALL TYPE ; ; Print N columns, alphabetically down ; Divide number of entries by N to get # lines ; LHLD NCOLS ;Get # of columns PUSH H STA TEMP1 CMP L ;Is it the last one ? POP H ;Clean stack in case ; new line needed JZ NEWLIN ;Do next line if yes PUSH H nes ; ; Now print the index ; NEWLIN: LXI D,CRLF CALL TYPE ;Do a C/R, L/F XRA A STA TEMP1 ;Reset # columns done LHLD INDEX ;Get pointer address PUSH A,L ;Remainder to A STA TEMP ;Save # partial cols. ORA A JZ EVENLN ;If even # lines INX B ; Else bump # lines EVENLN: PUSH B ;Save # li pointer JMP NXTONE ;And try to do another ; ; MESSAGE OUTPUT ROUTINE ; HL = DATA ADDRESS, B = CHARACTER COUNT ; WRTMSG: MVI C,WRTCON ;USE CP/M WRITE CONSOLE FUNCTION LDA PFLAG ;GET PFY',0DH,0AH,'$' CONFRM: DB 7,'MODIFY FILE, CONFIRM (Y/N)? $' ; HEADER: DB ' ' DB 'DIRECTORY - ' ASCTTL: DB 'DRIVE ' ASCDSK: DB ' ' CRLF: DB 0DH,0AH,'$' ; FUSED: DB ;TIMES 10 ADD D ;ADD THIS ONE MOV E,A ;SAVE IN E INX H ;BUMP ADDRESS DCR C ;ANY LEFT JNZ CNVBA1 RET ; ; UPPER CASE T EXCEPT IT GOES TO CONSOLE OR LIST DEPENDING ON FLAG ; TYPE: MVI C,WRTCON ;SET FOR CONSOLE OUTPUT LDA PFLAG ;GET PRINTER FLAG ORA A ;WANT PRINTER? JZ TYPE1 ;SKIP IF N, ETC CALL TYPE LDA OLDDSK ;SELECT ORIGINAL DISK MOV E,A ;TO E-REGISTER MVI C,SLDISK ; (EVEN IF NEVER DESELECTED) CALL CPM CPMRET: LHLD SPSAV ;GET OLD CPI '/' ;ANOTHER SEPARATOR RZ CPI '0' ;CHECK FOR NUMERIC RC ;RETURN IF NOT CPI '9'+1 CMC RC SUI '0' ;MAKE IT BINRINTER FLAG ORA A ;WANT PRINTER? JZ WRTMSG1 ;SKIP IF NOT MVI C,WRTPRN ;OTHERWISE SET FOR PRINTER WRTMSG1:MOV E,M ;GET DATA PUSH B PUSH H E RET ; ; PRINT A SPACE ; PSPACE: MVI E,' ' ;GET A SPACE MVI C,WRTCON LDA PFLAG ;WANT PRINTER ORA A JZ PSPC1 MVI C,WRTPRN ;WET UP FOR PRINTERANSLATION ; UCASE: CPI 'A'+32 ;LOWER CASE? RC ;RETURN IF NOT CPI 'Z'+33 ;WITHIN RANGE? RNC ;RETURN IF NOT SUI 32 ;FORCE TO UPPER CASOT MVI C,WRTPRN ;SET FOR PRINTER OUTPUT TYPE1: LDAX D ;GET CHARACTER CPI '$' ;END OF STRING? RZ ;DONE IF SO PUSH D ;SAVE REGISTERS STACK SPHL RET ;AND RETURN ; ; MESSAGES ; ERMSG: DB 'INVALID FILE NAME',0DH,0AH,'$' OPERR: DB 'INVALID OPTION IGNORED',0DH,0AH,'$' FFMSG: DB 12,'$' MFERR: DB 'FILE ERROR DURING MODIARY MOV D,A ;SAVE IN D MOV A,E ;GET PARTIAL RESULT ADD A ;TIMES 2 ADD A ;TIMES 4 ADD E ;TIMES 5 ADD A ;SAVE ADDRESSES CALL CPM POP H POP B INX H DCR B ;DONE? JNZ WRTMSG1 ;LOOP IF NOT RET ; ; TYPE - EQUIVALENT OF CP/M WRITE BUFFER ; R PSPC1: CALL CPM RET ;THAT'S ALL THERE IS TO IT ; ; PRINT DONE, OUTPUT BOTTOM LINE AND RETURN ; PRTDON: POP D ;Clean up stack POP D LXI D,FUSED ;NUMBER OF FILES, SPACENARY CONVERSION ; HL POINTS TO DATA, RESULT RETURNED IN E ; CNVBA: MVI E,0 ;CLEAR RESULT CNVBA1: MOV A,M ;GET CHARACTER CPI ' ' ;SEPARATOR? RZ ;RETURN IF SO PUSH B MOV E,A ;DATA TO E CALL CPM ;TYPE IT POP B POP D INX D ;BUMP ADDRESS JMP TYPE1 ;LOOP FOR MORE ; ; ASCII TO BI 0DH,0AH,0AH,' ' ASCNUM: DB ' FILES (' ASCEXT: DB ' ENTRIES)' CRPOS: DB ' ' ASCUSE: DB ' K USED ' FREE: DB ' K FREE',0DH,0AH,'$' ; COLSEP: ;Will redefine later SPACES: DBX {/OPTIONS} {DRIVE:}{FILENAME}{.}{FILETYPE} where all of the parameters in the braces are optional. Wild card characters (* and ?) can be included in the file name designations. The following example commands, and their results, illustrate the wild ;FILE NAME PART FTYPE: DB '???' ;FILE TYPE EX: DB '?' ;EXTENT (ALL OF THEM) DW 0 ;TWO UNUSED BYTES DB 0 ;RECORD COUNT DS 20 ;FILLED Denver, Colorado 80227 Copyright (C) 1981 INDEX is a CP/M (R) utility program combining the features of DIR and STAT. It provides an alphabetical listing of the disk directory, spaced in columns across the sc ;ADDRESS FOR TITLE SPSAV: DS 2 ;FOR STACK POINTER OLDDSK: DS 1 ;OLD DISK NUMBER EXTCNT: DS 2 ;EXTENT (DIRECTORY ENTRIES) COUNT SWAP: DS 1 USRNO: DS 1 ;USER NUMBER ; ' $' ; ; VARIABLES ; NUMBER: DW 0 ;NUMBER OF DIRECTORY ENTRIES READ MLTPLS: DW 0 ;NUMBER OF MULTIPLE EXTENTS DSKSEL: DB 0 ;DISK SELECT FLAG TFLAG: DB 0 ;TITLIN BY CP/M DSKSZ: DS 2 ;DISK SIZE IN K BLKSZ: DS 1 ;BLOCK SIZE IN K BLKREC: DS 1 ;RECORDS PER BLOCK BLKSHF: DS 1 ;BLOCK SHIFT FACTOR EXTMSK: DS 1 ;EXTENT reen, and may include the file size for each entry. The total number of files, the total number of directory entries used, the disk space used, and the disk space remaining is also reported. The general form of the command is INDE DS 64 ;FOR LOCAL STACK STAK EQU $ MBUF EQU $ ;REST OF MEMORY FOR BUFFER CKBUF EQU MBUF + 1536 ;CHECK BUFFER END E FLAG UFLAG: DB 0 HDRADR: DW HEADER ;HEADER ADDRESS ; INXFCB: DB 0,'INDEX COM',0,0,0,0 DS 16 INXRC: DB 0,0,0,0 FCB: DB 0 ;FILE CONTROL BLOCK, BYTE 1 FNAME: DB '????????' INDEX PROGRAM Version 3.0 by F. J. Greeb 1915 S. Cape Way ;ADDRESS STORAGE FLGADR: DS 2 ;FLAG ADDRESS TEMP: DS 2 ;GENERAL PURPOSE STORAGE TEMP1: DS 2 ; MORE OF THE SAME TEMP2: DS 2 ; AND 1 MORE TTLADR: DS 2 MASK STORAGE INDEX: DS 2 ;POINTER TO INDEX ARRAY BLKS: DS 2 ;TOTAL BLOCKS ON DISK USED: DS 2 ;TOTAL SPACE USED BY FILES NCOLS: DS 2 ;# columns BUFADR: DS 2 character capability of the program. INDEX Directory of all files on current drive INDEX B: Directory of all files on drive B INDEX *.COM Directory of all COM files on drive B fault value. See the note below concerning this option. /V Reports the version number for the INDEX program you are using. Please include this version number when rted. This mode is useful for large directories, since more columns will fit on the screen. /Wn Set the output width to n, where n is a number in the range of 32 to the directory search. Use this option if you change disks without doing a Control C. /P Directs the output to the printer rather than to the console. e, INDEX /B/M will modify the program so that the brief mode is the normal state. Including the /B command will then cause the expanded output form to be used. /Tk name file with a dash as the first character, the disk name may be used as the title by using a /T- option. This form of the title option causes the INDEX program to read the disk name INDEX A??.* Directory of all three letter or less file names begining with the letter A on the current drive INDEX B:A*.* Directory of all files on dri The number of columns is automatically adjusted to fit the width you specify. /S Include system files in the directory listing (CP/M Version 2 only). System files are 255. This command can be used to adjust the program for screens smaller than the nominal value of 80, or to set the width to a larger number for directories sent to the printer. /F Outputs a form feed character (Control L) before printing the directory (console or printer). /T Allows a title to be input (immediately following the T) which will replace the-/M will cause the title to default to the disk name. If no disk name is found, the normal DRIVE A title will be used. You can not set up any other title as the de and substitute it for the normal title. /B Sets the brief mode. The size reporting for each individual file is suppressed. The total disk space used is still repove B which begin with the letter A, regardless of the file name length. OPTIONS - The options which are allowed are: /R Resets the disk system before performing normally suppressed from the directory. This option allows you to display them. /M Modify the program to reset any of the above options to the default value. For exampl title, use the underline character. The underline will be translated to a space before the title is printed. If you are using the Master Catalog Program and your disks have a dis DRIVE designator on the directory output. The maximum title length is 20 characters, and no spaces may be contained in the input title. To include spaces in the output reporting any bugs or suggested improvements to the program. /Un Lists the directory for user number n, where n is a number in the range of 0 to 15 (CP/M Version 2 onoption allows the disk space remaining to be reported correctly, without having to input a Control C after each disk change. After you have printed all of the desired directories, the program output can be restored to the console by using the coINDEX.COM program is on the default disk. If you are logged on to Drive A, and you issue the command B:INDEX /B/M to set the default to the brief mode, the program will search for a program named INDEX.COM on Drive A. If you do not have a second copy oand INDEX /R/P /F/TSYSTEM_FILES B:*.COM will reset the disk system, use a title of SYSTEM FILES, and output the directory of all COM files on drive B to the printer, with a leading form feed. A little experimentation with the options andrestore the program to its original state. For example, if you want to list a series of directories on the printer, with a leading form feed for each printout, the command INDEX /P/F/R/M can be used to set up the desired default mode. Yng that the program does not recognize. The error is ignored and all other options are still in effect. FILE ERROR DURING MODIFY - Indicates that the modify option was not completed successfully. This can occur if the file INDEX.COM is notly). /H Print a short help message on the console, which lists all of the available options. The options may be chained together by separating then with a slash, which is used as the option designatorthat it will be destroyed. The modify command performs a check for the correct version number and a partial contents comparison before allowing the modify operation to be completed, but this is not completely foolproof. The modify command asks for cof the program on Drive A, an error will be reported and no serious consequences will result. However, if there is a file named INDEX.COM on Drive A, and it is not the same as the program on Drive B, or is a completely different program, it is possible file name wild card characters will give a better understanding of their operation. Note that all inputs may be in either lower or upper case, and are translated internally to upper case only, in keeping with the CP/M format. This does not include thou can then list all of the disks, assuming you are logged on to Drive A, using the command INDEX B: The new default values eliminate the need to list the options separately for each disk that you put in the B drive. Including the reset found on the default disk, if the program and disk version numbers do not match, or if a disk write error occurs. Modify Option A word of caution if you use the Modify option. This option requires that the character. Chained options may appear in any sequence and may also include a space as a separator if desired. There must be at least one space following the last option and any drive or file designator which is included. For example, the commnfirmation before updating the program so if you input the modify option by mistake you can abort it before any harm is done. The modify command can be used to set up a default value for performance of a series of runs, and then be used again to e specified is not a valid CP/M file name. This usually means that it is too long, although other problems can cause this error message to appear. UNRECOGNIZED OPTION IGNORED - Indicates that an option has been included in the command strie titles, which may be output in upper or lower case. Error Messages There are three error messages which may be output by the program. These are: INVALID FILE NAME - Indicates that the file nammmand INDEX /P/M The /P option toggles the printer flag, and since the current default was for printer output, this returns the default to the console. Also, since the /F and /R options were not reset, they are still in effect as the defoutine ; issues an error message and continues. Added ; check for 'first time flag' to exit routine so ; if no file is found meeting the requested ; parameters, '++NOT FOUND++' is issued to the ; console. NOTE: This required modifying the ma(Micromodem autodial) D to disconnect the phone (Micromodem ][ only) H to print this help file Secondary options: A answer mode O originate mode D disconnect after execution T go to terminal mode after file xfer E go to echo Operating Restrictions The program is configured in a general manner and should work with any version of CP/M, with mini-disks, 8 inch disks, or even hard disks. The program has been tested with CP/M Version 1.4 and 2.2 using both singf file. (KBP) ; ;09/20/80 Added ILPRT routine, revised messages, added new ; abort routine, added CP/M 2.x f1' protect test, ; cleaned up file. (KBP) ; ;09/09/80 Revised check for '.COM' and '.OBJ' files so ; during attempt to list multiple fir them has not been included in the program. If you have a file of this type, the CP/M STAT command can be used to verify the file size. CP/M is a registered trademark of Digital Research. OK ault mode. Using this technique, you can set up any available options that you desire as the default mode. Note that only options preceeding the /M option in the command line will be modified. A command of the form INDEX /B/M/P will seile: MODEM S fn.ft Then send a third file at 110 baud and disconnect: MODEM SD.110 fn.ft Act as a terminal, originate mode, at 110 baud: MODEM TO.110 (Use ctl-D to disconnect) Receive file, answer mode, view it, 110 baud: MODEM RAV mode after file xfer Q quiet mode - no status msgs R show chars received S show chars sent V view file sent/received (no status) FOR EXAMPLES, TYPE: MODEM X ͳ Send file, originate mode, 300 baud: MODEM SO fn.ft Send another fle and double density 8 inch disks, and with Version 2.2 using mini disks and hard disks. Please report any errors or bugs which are detected to the author at the address listed above, including the INDEX version number as reported by the /V option, ales these ; would not abort the routine. Modified to ; issue an error message and continue with the ; next valid file. Added check for '#' character ; as the last character in the file type indicat- ; ing the file was not for distribution. R character primary option, which may be followed by sub-options, and by ".xxx" to set baud rate to xxx Primary Options: S to send a file R to receive a file T to act as a terminal E to act as a computer (echo data) C to connect nd a brief mode directory to the printer, but only the brief mode will be reset as the default value. Since the /P option is after the /M option, the printer will be used for this run only, rather than becoming the default mode. .110 fn.ft Autodial a number, and connect at .110 baud (300 baud is default) MODEM C.110 e mode, at 110 baud: MODEM TO.110 (Use ctl-D to disconnect) Receive file, answer mode, view it, 110 baud: MODEM RAVinitially writing only record 10 and record 2356), the file size reported may not be correct. Since this type of file occurs only rarely (most random files are initially created sequentially) the extra code necessary to assure correct size reporting fond as much detail about the system configuration and disk status as possible. There is one known case where file sizes may not be reported correctly. If you use the random write capability of CP/M Version 2, and write a file with holes (such as !9"A1A APXMODEM ver 4.1 :]͟::SʉR++INVALID OPTION ON XMODEM COMMAND++ Must be S for SEND or R for RECEIVE $oͭ%P͐"ڶ%2͙͆ͧͬڤ×>oͬڶo!e>C)#>O)#>M)++CAN'T RECEIVE A .COM FILE++ tialization required) to TRUE. The conditional assembly will then take place properly for you modem. The modem program is very simple to use and self documenting if you type MODEM H (for help). The program is controlled by theed the protocol for CP/M file transfer via modem. Apple CP/M is a full 56k standard CP/M, but is limited in that the disk format is unique to Apple. This inhibits the exchange of software, which is distressing since one of the main advantages of > oXMODEM PROGRAM CANCELLED $:<2\<++FILE EXISTS - USE A DIFFERENT NAME++ $2h2|\<++ERROR - CAN'T MAKE FILE++ Directory must be full $>?2h>2\<++FILE NOT FOUND++$\<:o&T:_)))))))"=n with the Micromodem II. Version 2.0 implements auto- dialing feature of this modem, while version 1.0 does not. To make the COM file, simple type ASM APMODEM2 (of course, the assembler, ASM.COM must be on the disk) and then LOAD APMODEM2. If yCOr2Ð!l\2|2h_ 0ò~Ͳ# *A~# Rename filetype ".OBJ" and try again $-cFILE OPEN - READY TO RECEIVE c͠%̀Q͸̀!]~ ˜++NO FILE NAME SPECIFIED++ $ ~?ʦ#š++CAN'T USE WILD CARD OPTIONS $2 *-7>o:<2 bout any modem set-up currently extant on the Apple. It has been tested with the D.C. Hayes Micromodem II, the CCS 7710A serial interface, and the Apple communications card. It should also work with the SSM serial board, but I have not tested it with CP/M is the extensive amount of public domain software available. With this modified version of Ward's program, coupled with the many remote CP/M systems, all of this software is now available to Apple users. This program should work with just a!oF+++:x2~22h2|\o>o:o:/o!~o,žyo :<2 ++CAN'T SEND SECTOR - ABORTING++ $÷1A>othis board or the Apple serial interface. Should you find that it doesn't work with these, please let me know, or even better, fix the program so that it works! The program is supplied as an ASM file, and will assemble without modification to ru+ERROR WRITING FILE++ $::P:E"":O7:Oc:Q xgO:ʋ:Or2Ð!l\2|2h_ 0ò~Ͳ#