page@swan.ulowell.edu (Bob Page) (02/03/89)
Submitted-by: rick@QUCDNAST.BITNET Posting-number: Volume 89, Issue 16 Archive-name: util/fixfd.1 # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # ReadMe # FixFD.asm # FixFD.docs # FixFD.link # FixFD.uu # Std_Start.uu # This archive created: Mon Jan 30 18:53:00 1989 cat << \SHAR_EOF > ReadMe To : Aspiring M68000 Programmers From: Peter Wyspianski Date: 01 Jan 89 As I was getting ready to archive my 'FixFD' utility, it occured to me that some aspects of programming the Amiga would have been a LOT easier to learn if I just had a few examples to look over. I came to the Amiga programming enviroment from the MacIntosh. So I was no stranger to the M68000 or the sort of things you have to do with it in such a complex enviroment. Still, it has been a struggle. While writing this utility I had to learn how to detect the user hitting 'ctrl-c' to abort the program. No big deal, but I wasted a couple hours looking in the wrong places for the information (the AmigaDOS manual and some magazines). Turns out it is not really documented anywhere, at least not specifically. But I wonder where I would be now if I was a complete novice M68000 programmer? It's not like the 6502 days when you could just drop into a machine language monitor and hand-code some instructions to see what they do (that is how I first learned ML). I have decided to include the source code for the main program. You may study it, and even use the routines if you like. I just hope you learn something. I have NOT included my 'Std_Macs68k' file. This file just contains a bunch of macros that match my programming style. For example, if I am testing a register for zero, I like to be able to code 'bz.s xxx' rather then the more ambiguous 'beq.s xxx'. So in my macro file I have a macro called 'bz'. I have also not included the 'dos_lib.i' file. This file can be created by using FixFD like so: >FixFD dos_lib.fd dos_lib.i in my case, I then edited the dos_lib.i file to add a 'PREASM' option and ran it through the assembler (CAPE68k from Inovatronics). This feature of CAPE lets it inhale the 'INCLUDE' file without pausing to assemble it. A real timesaver in larger projects. This step is entirely optional. Finally, the code must be linked with Std_Startup.obj. This file is my customized version of AStartup.obj. I have included 'Std_Startup.obj' but not the source code for it. If you want to play around with FixFD, you could link with AStartup.obj instead. Here is how you get the link to work: >BLink with FixFD.link if you don't happen to have the freely-redistributable 'BLink' then substitute the name of your linker (probably 'ALink'). The file 'FixFD.link' is also included. Take a look at it, because it expects to find everything in 'RAM:'. Good luck! Remember to read the docs. And if you have any questions or comments then please send me a postcard (my address is in the docs). -Peter W.SHAR_EOF cat << \SHAR_EOF > FixFD.asm ; file:FixFD.asm ;----------------------------- ; Fix FD ;----------------------------- ; A utility to convert FD files to EQU files. ; ; Copyright (c) 1988 by Peter Wyspianski ; ; Revision History ; ---------------- ; 30 Dec 88 created ; 01 Jan 89 changed to use the 'dos_lib.i' file ;---------------------------------------- ; Constants null equ $00 bs equ $08 tab equ $09 lf equ $0a ; amiga eoln cr equ $0d ; CR only esc equ $1b csi equ $9b ; control sequence introducer ; DOS Constants: MODE_OLDFILE equ 1005 MODE_NEWFILE equ 1006 SIGBREAKB_CTRL_C EQU $0C SIGBREAKB_CTRL_D EQU $0D SIGBREAKB_CTRL_E EQU $0E SIGBREAKB_CTRL_F EQU $0F SIGBREAKF_CTRL_C EQU $1000 SIGBREAKF_CTRL_D EQU $2000 SIGBREAKF_CTRL_E EQU $4000 SIGBREAKF_CTRL_F EQU $8000 ;**SIGBREAK_ANY equ $F000 SIGBREAK_ANY equ $1000 ; Exec Base Offsets: ThisTask EQU $114 ; Task Control Structure Offsets: TC_SIGRECVD EQU $1A TC_SIGALLOC EQU $12 ;---------------------------------------- ; Includes MACFILE "RAM:Std_Macs68k" INCLUDE "RAM:dos_lib.i" ;---------------------------------------- ; Publics XDEF _main XDEF Exit ;---------------------------------------- ; Externals: ; from std.startup: XREF _exit XREF _stdin,_stdout,_SysBase,_DOSBase ;---------------------------------------- ; The beginning SECTION Main,CODE ; just a little something to brighten some file-zapper's day: dc.b 'Be Happy!',null cnop 0,2 ;------------------------------- ; BCD_Left [18 Nov 88] ; ; - converts hex word to a string of one to five left justified BCD digits ; - string is null terminated ; ; Inputs : d0.w = hex word ; a0.l = starting address of string ; Outputs: all regs preserved ; ; Notes : - from 1 to five digits can be returned plus the zero termination ; for a total of up to six characters ; - starts by determining number of digits in the string BCD_Left pushm d0-d3/a0-a1 move.w #3,d2 ; # digits - 2 lea LBCDTAB,a1 ; point to ten thousands 1$ cmp.w (a1)+,d0 ; determine number of digits in result bcc.s 2$ ; (ubge) taken if right size dbra d2,1$ ; taken for 10K through 10 bra.s 6$ ; we have just a ones digit 2$ subq.l #2,a1 ; compensate for following pre-decrement 3$ move.w (a1)+,d1 ; d1=BCD digit weight move.b #'0',d3 ; init digit to ASCII '0' 4$ cmp.w d1,d0 ; digit weight ? remainder blt 5$ ; taken if done with this digit addq.b #1,d3 ; inc BCD digit result sub.w d1,d0 ; decrement total bnz.s 4$ ; go for more 5$ move.b d3,(a0)+ ; stash digit dbra d2,3$ ; next digit position 6$ or.b #'0',d0 ; form ones digit move.b d0,(a0)+ clr.b (a0) ; form zero terminator pullm d0-d3/a0-a1 rts LBCDTAB dc.w 10000,1000,100,10 ;---------------------------------------- ; GetDec [30 Dec 88] ; ; - converts a decimal string to a hex value ; ; Inputs : a0 = ^ string ; Outputs: d0.l = value ; ; Reg Use: d1,a0-a1 ; ; Calls : none ; Uses : none ; ; Notes : - Non-numeric input produces garbage (GIGO applies). ; - Excessively long strings cause wrap-around. GetDec: clr.l d0 ; result 1$ move.b (a0)+,d1 ; fetch next digit bz.s 2$ ; if 'digit' is a null then all done ; here the running result is multiplied by ten: asl.l #1,d0 ; x2 move.l d0,a1 ; save the x2 value (a1 = scratch) asl.l #2,d0 ; x4 x8 add.l a1,d0 ; x8 + x2 = x10 ; the latest 'units' digit is added to the result: sub.b #'0',d1 ; force digit to range 0-9 add.l d1,d0 ; splice into result bra.s 1$ ; and go for more! 2$ rts ;---------------------------------------- ; PrStr [31 Dec 88] _stdout ; FPrStr [31 Dec 88] a file ; ; - sends a null terminated string to a file (_stdout) ; ; Inputs : a0 = ^string ; a1 = file handle (FPrStr only) ; ; Outputs: none ; ; Calls : Write (DOS.Library) ; Uses : _DOSBase (library base) ; _stdout ; ; Notes : exits via the call to Write PrStr: move.l _stdout,a1 FPrStr: push.l a1 ; save file handle move.l a0,a1 ; find the string length 1$ tst.b (a1)+ bnz.s 1$ ; loop until end of string sub.l a0,a1 ; start-end+1 = len+1 sub.l #1,a1 ; fix the length pull.l d1 ; recover file handle move.l a0,d2 ; ^buffer move.l a1,d3 ; length move.l _DOSBase,a6 jmp _LVOWrite(a6) ; exit via this routine ;---------------------------------------- ; ReadLn [31 Dec 88] from _stdin ; FReadLn [31 Dec 88] from a file ; ; - reads a line from a file (_stdin) ; - terminator (lf) is NOT stored ; - string is returned null-terminated ; ; Inputs : a0 = ^string buffer ; a1 = file handle (FReadLn only) ; ; Outputs: d0 = result: 1 = ok, 0 = eof, -1 = error ; ; Reg Use: d0-d3/a0-a2 ; ; Calls : Read (DOS.Library) ; Uses : _DOSBase (library base) ReadLn: move.l _stdin,a1 FReadLn: move.l a0,a2 ; keep ^buffer safe move.l a1,a3 ; keep file handle safe 1$ move.l a3,d1 ; file handle move.l a2,d2 ; ^buffer move.l #1,d3 ; read one char CallDOS Read cmp.l #1,d0 ; what was returned? bne.s 2$ ; exit if error or eof move.b (a2)+,d1 ; fetch character and bump ^buffer cmp.b #lf,d1 ; end of line? bne.s 1$ ; taken if not 2$ move.b #null,-1(a2) ; null terminate the string rts ; and exit ;---------------------------------------- ; FileOpenError [31 Dec 88] ; ; - calls IoErr to get a specific error number for a failed file open. ; - prints an error message of the form: ; ; Error #xxx opening file "yyyy". ; ; ; Inputs : a0 = ^filename ; Outputs: none ; ; Reg Use: d0-d1/a0-a1 ; ; Calls : IoErr (DOS.Library) ; BCD_Left ; PrStr ; Uses : _DOSBase (library base) ; BCDBuff FileOpenError: push.l a0 ; save ^file name CallDOS IoErr ; must do this FIRST push.w d0 ; save the bad news lea BadOpenMsg,a0 jsr PrStr pull.w d0 ; recover error number lea BCDBuff,a0 jsr BCD_Left lea BCDBuff,a0 jsr PrStr ; show the number lea BadOpenMsg1,a0 ; second half of error message jsr PrStr pull.l a0 ; fetch ^file name jsr PrStr lea BadOpenMsg2,a0 ; third half of error message jsr PrStr rts *---------------------------------------- * Main [30 Dec 88] * * here is a picture of the entry stack: * * 12 --- not ours! * 8 ^argvArray pointer to argvArray * 4 argc argument count * sp 0 RA our return address _main: clr.l TheError ; default good return move.l sp,savesp ; to ensure that we clean up on exit pull.l ReturnAddr ; just in case we need it... ; make a pointer to our TC_SIGRECVD: move.l _SysBase,a0 ; base of the Exec library move.l ThisTask(a0),a0 ; ^Task Control Structure (that's us!) lea TC_SIGRECVD(a0),a0 ; ^the flags move.l a0,TaskSigs ; save the pointer for later ; and we're off: lea GreetMsg,a0 ; say hello jsr PrStr pull.l argc ; argc (argument count) pull.l argv ; ^argv (argument array) move.l argc,d0 ; argv format: <name> <source> <dest> cmp.l #3,d0 ; we need three arguments... blt.l Help ; ...taken if 'confused user' error! move.l argv,a0 ; fetch ^argv move.l 4(a0),a0 ; point to first argument move.l a0,SName ; save ^source file name move.l argv,a0 ; fetch ^argv move.l 8(a0),a0 ; point to second argument move.l a0,DName ; save ^dest file name ; open the input file: move.l SName,d1 move.l #MODE_OLDFILE,d2 ; must already exist CallDOS Open move.l d0,sfile ; save source file handle bnz.s 1$ ; taken if ok ; handle problems opening the input file: move.l SName,a0 jsr FileOpenError move.l #30,TheError bra.l Exit ; bye! ; open the output file: 1$ move.l DName,d1 move.l #MODE_NEWFILE,d2 CallDOS Open move.l d0,dfile ; save dest file handle bnz.s ScanFD ; taken if ok ; handle problems opening the output file: move.l DName,a0 jsr FileOpenError move.l #30,TheError bra.l Exit2 ; read lines of the input file until EOF is true: ScanFD: ; If the output file is acutally the tube then we don't want ; line numbers cluttering the display: move.l dfile,d1 ; output file handle CallDOS IsInteractive move.b d0,TubeOut ; -1 = yeah, 0 = nope lea HeaderMsg,a0 move.l dfile,a1 ; output file handle jsr FPrStr move.l DName,a0 move.l dfile,a1 ; output file handle jsr FPrStr lea HeaderMsg1,a0 move.l dfile,a1 ; output file handle jsr FPrStr tst.b TubeOut ; skip screen formatting if outfile... bnz.s 1$ ; ... is connected to the tube. lea StatusMsg,a0 jsr PrStr lea CursorOff,a0 jsr PrStr 1$ move.w line,d0 ; bump line number add.w #1,d0 move.w d0,line tst.b TubeOut ; gonna use the tube? bnz.s 8$ ; taken if not (being used by out file) lea BCDBuff,a0 ; convert line number to a dec string jsr BCD_Left lea BCDBuff,a0 ; show the line number jsr PrStr ; This gets REAL fancy by adding one 'bs' to StrBuff for every ; non-null char in BCDBuff: lea BCDBuff,a0 lea StrBuff,a1 2$ move.b #bs,(a1)+ ; put one in there tst.b (a0)+ ; check for a null bnz.s 2$ ; taken if not move.b #null,-1(a1) ; kill the last bs and null terminate lea StrBuff,a0 ; backup jsr PrStr 8$ move.l TaskSigs,a0 ; see if the user hit ctrl-c thru ctrl-f move.l (a0),d0 ; d0 = SigsRecvd and.l #SIGBREAK_ANY,d0 ; mask all but ours bnz.l Abort ; taken if we hit lea StrBuff,a0 ; fetch a line from the input file move.l sfile,a1 jsr FReadLn tst.l d0 ; see what's up! bz.l Exit0 ; taken if EOF bmi.l Exit0 ; taken if error ;---------------------------------------- ; determine what sort of line it is here: ; ; # = option (process further) ; A-Z,a-z,'_','.' = FD entry (strip) ; ; all others are ignored ('*',';', and anything else) move.b StrBuff,d0 ; fetch first char cmp.b #'#',d0 ; option? beq 6$ ; taken if so cmp.b #'.',d0 ; fd entry? beq.s 3$ ; taken if so cmp.b #'_',d0 ; fd entry? beq.s 3$ ; taken if so cmp.b #'A',d0 ; fd entry? blt.l 1$ ; taken if NOT (ignore) or.b #$20,d0 ; force to lowercase cmp.b #'z',d0 ; fd entry? bgt.l 1$ ; taken if NOT (ignore) ;--------------------------------------------------------------- ; strip the line (scan for a space, open paren, or end of line) ; there are NO blank lines here (eliminated above): ; 3$ lea LVOMsg,a0 ; prefix the routine name with '_LVO' move.l dfile,a1 jsr FPrStr lea StrBuff,a0 5$ move.b (a0)+,d0 ; fetch a char and bump pointer bz.s 4$ ; taken if end of line cmp.b #' ',d0 ; space? beq.s 4$ ; taken if so cmp.b #'(',d0 ; open paren? bne.s 5$ ; taken if so 4$ move.b #null,-1(a0) ; null-terminate right AT the 1st excess char pea -1(a0) ; save ^end of string (for later) lea StrBuff,a0 ; show the line move.l dfile,a1 ; output file handle jsr FPrStr lea StrBuff,a0 pull.l d0 ; fetch ^end of string ;*** sub.l a0,d0 ; d0 = string len ;*** lea EQU8Msg,a0 ; <tab> <tab> equ <tab>- ;*** cmp.l #8,d0 ; seven chars or less? ;*** blt.s 44$ ; taken if so (output extra tab) lea EQUMsg,a0 ; <tab> equ <tab>- 44$ move.l dfile,a1 ; output file handle jsr FPrStr move.w bias,d0 ; convert the bias to a decimal string lea BCDBuff,a0 jsr BCD_Left lea BCDBuff,a0 move.l dfile,a1 ; output file handle jsr FPrStr ; show the bias lea EQUMsg1,a0 ; finish the line off move.l dfile,a1 ; output file handle jsr FPrStr move.w #6,d0 ; bump bias add.w d0,bias bra.l 1$ ; and go again! ;---------------------------------------- ; check for the '##bias' option: 6$ move.l StrBuff+2,d0 ; fetch 4 chars (should be 'bias') or.l #$20202020,d0 ; force to lowercase cmp.l #'bias',d0 bne.l 1$ ; ignore if not the option ; scan for a space: lea StrBuff+6,a0 ; skip the '##bias' 7$ move.b (a0)+,d0 ; fetch a char and bump pointer bz.l 1$ ; taken if end of line (ignore) cmp.b #' ',d0 ; space? bne.s 7$ ; taken if not ; fetch and show the bias: jsr GetDec ; a0 should be pointing at the number move.w d0,bias ; save it ; show the 'bias = ' message: lea BiasMsg,a0 move.l dfile,a1 ; output file handle jsr FPrStr move.w bias,d0 ; convert the bias to a decimal string lea BCDBuff,a0 jsr BCD_Left lea BCDBuff,a0 move.l dfile,a1 ; output file handle jsr FPrStr ; show the bias lea BiasMsg1,a0 move.l dfile,a1 ; output file handle jsr FPrStr bra.l 1$ ; go for another line ;------------------------------------------- ; show the help message and exit: Help: lea HelpMsg,a0 jsr PrStr bra.s Exit ;------------------------------------------- ; show the 'break...' message and exit: Abort: lea BreakMsg,a0 jsr PrStr bra.s ExitA ;----------------------------- ; Exit routines [30 Dec 88] ; Exit0: lea DoneMsg,a0 jsr PrStr ExitA: lea CursorOn,a0 jsr PrStr Exit1: move.l dfile,d1 ; close the dest file CallDOS Close Exit2: move.l sfile,d1 ; close the source file CallDOS Close Exit: push.l TheError ; error code jsr _exit ; and wind it up ;---------------------------------------- ; constants SECTION Constants,DATA GreetMsg: dc.b lf dc.b csi,'0;33;40m' dc.b ' FixFD ' dc.b csi,'0;31;40m' dc.b 'v1.0 - Copyright ',$a9 dc.b ' 1988, Peter Wyspianski',lf,lf dc.b null HelpMsg dc.b ' This utility takes an ''.FD'' file and generates a set of',lf dc.b ' EQUates that can be used by an assembler.',lf,lf dc.b ' Parameters: source_file dest_file.',lf,lf dc.b ' See the docs for more info! -PW',lf,lf,null BadOpenMsg: dc.b csi,'0;33;40m' dc.b ' Error ' dc.b csi,'0;31;40m' dc.b '#' dc.b null BadOpenMsg1: dc.b ' opening file "',null BadOpenMsg2: dc.b '"',lf,lf,null CursorOff dc.b csi dc.b '0 p' dc.b null CursorOn dc.b csi dc.b ' p' dc.b null StatusMsg: dc.b ' Reading line ' dc.b null DoneMsg dc.b lf,lf dc.b csi,'0;33;40m' dc.b ' Finished.' dc.b csi,'0;31;40m' dc.b lf,lf,null BreakMsg dc.b lf,lf ;*** dc.b csi,'0;33;40m' dc.b '*** BREAK' ;*** dc.b csi,'0;31;40m' dc.b lf,lf,null HeaderMsg dc.b '; file:',null HeaderMsg1 dc.b lf dc.b ';',lf dc.b '; generated by FixFD v1.0',lf dc.b ';',lf dc.b null BiasMsg dc.b '; Bias = ',null BiasMsg1 dc.b lf dc.b ';',lf dc.b null LVOMsg dc.b '_LVO',null EQU8Msg dc.b tab EQUMsg dc.b tab dc.b 'equ -' dc.b null EQUMsg1 dc.b lf dc.b null ;---------------------------------------- ; Uninitialized storage SECTION Variables,BSS TaskSigs ds.l 1 ; pointer to our TC_SIGRECVD TheError ds.l 1 ; error return code SName ds.l 1 ; ^source file name DName ds.l 1 ; ^dest file name sfile ds.l 1 ; source file handle dfile ds.l 1 ; dest file handle savesp ds.l 1 ; entry stack pointer argc ds.l 1 ; argument count argv ds.l 1 ; argument array pointer ReturnAddr ds.l 1 ; program return address bias ds.w 1 ; library entry bias line ds.w 1 ; current line number TubeOut ds.b 1 ; -1 = yes, 0 = nope ds.b 1 ; alignment BCDBuff ds.b 6 ; bcd string buffer StrBuff ds.b 256 ; longest possible string ENDSHAR_EOF cat << \SHAR_EOF > FixFD.docs FixFD v1.0 User Manual Copyright (C) 1988 by Peter Wyspianski [31 Dec 88] ---------------------- Please Read The Manual ---------------------- The FixFD utility is not complicated, but please take a couple minutes to read through this manual before you try it. Thanks! -------- Abstract -------- FixFD is a utility for the Amiga series of computers that reads an '.FD' file to produce an assembler 'include' file. ----------- Legal Stuff ----------- Amiga is a trademark of Commodore-Amiga, Inc. The author is in no way connected with Commodore-Amiga, Inc. The FixFD utility package, consisting of the program and documentation file, is copyrighted. Permission is granted for NON-COMMERCIAL distribution of UNMODIFIED copies of the entire package. All other rights are reserved. Distribution of separate parts of the package, or of modified copies is specifically prohibited. Failure to abide by these rules may result in a fine, and/or jail term. Additionally you may get a guilty conscience and I certainly won't visit you. Pass the word, pass this program! ----------------------- Who Needs This Utility? ----------------------- If you are an Amiga assembly language programmer (or want to be), then read on. Otherwise, this utility is NOT for you (sorry)! ----------- The Problem ----------- When you're programming in assembly language, the most common way to define a 'Library Vector Offset' (LVO) is to use the XLIB macro like so: XLIB Open ; DOS.Library XLIB Close ; DOS.Library where the 'XLIB' macro looks something like this: XLIB macro ; <routine name> xref _LVO\1 endm so by the time the assembler has sorted out those first couple of definitions here is what you got: xref _LVOOpen xref _LVOClose Later on in the program you may want to call the 'Open' routine: move.l DOSBase,a6 jsr _LVOOpen(a6) Of course most of us use a macro for those lines. But here is a question - just where IS the actual value of the symbol '_LVOOpen' defined? It is defined in the scanned library 'Amiga.Lib'! The problem is that Amiga.Lib is about 80K bytes long, and contains a LOT of things besides the _LVO definitions. Having the _LVOs defined in Amiga.Lib requires that you ALWAYS link your code with Amiga.Lib. This effectively neutralizes assemblers that produce loadable object files. It also makes for some very long link times. ------------ The Solution ------------ The ideal solution to the problem of having the LVOs defined in Amiga.Lib is to just equate them to their proper values: _LVOOpen EQU -30 _LVOClose EQU -36 Now you don't have to link with Amiga.Lib and the assembler will probably get done a bit sooner as it doesn't have to do as much work. To get these equates you simply use FixFD! ------------ What It Does ------------ The Extras disk includes a drawer called 'FDx.x' (where x.x is the operating system revision, currently '1.3'. Within this drawer are a number of files whose names end with '.FD'. These '.FD' files all have a standard format. They completely define all the LVOs within a particular library. The '.FD' files are updated with every new revision of the operating system. FixFD simply reads an '.FD' format file and cranks out a file that your assembler can read (using 'INCLUDE'). And thats all there is to it! You have a lot of choices when it comes to putting the resultant 'include' files to use. Adding a bunch of 'INCLUDE' statements is one possibility. Or you could merge them into one big include file. If your assembler supports 'preassembled symbols' then you can preassemble the LVO file(s) for lightning assembly speed! I like to have all the LVOs in one big file. That way I can use the cut-and- paste features of my text editor to put just the LVOs I need right into the assembly file I'm working on. There is probably a utility somewhere out there that does exactly the same thing as FixFD. Too bad I haven't seen it (yet)! So here is my contribution. Incidentally, it would have been far quicker to write this in something like BASIC, but I simply wanted some practice at working with DOS files from assembly. ----------- Using FixFD ----------- From the CLI (Command Line Interpreter) or Shell type: >fixfc source_file dest_file where 'source_file' is the name of the '.FD' file you want to read and 'dest_file' is the name of the new file you want to make You can use an asterix ('*') for the dest file, to send output to the CLI window. In that case the fancy line number display is suppressed so it doesn't tangle up the output. FixFD can be aborted in the usual way (ctrl-c). And if you forget one of the file names (or use '?'), you get a little blurb reminding you what to do. It DOESN'T work from WorkBench so don't try it (crashes the system). I could make it WorkBench compatible but why bother? Thats about it. I sure hope you like it! -------------------- So How Does It Work? -------------------- [This section is for the curious; it may be safely skipped by others.] FixFD scans each line of the input file looking for one of the following: ##bias xx Where xx is a decimal number 0-65535. Sets the base from which subsequent LVOs are calculated. Defaults to zero. The usual value is 30. <LVO name> <whatever> An LVO name is any line that starts with one of these characters: a-z, A-Z, period ('.'), underline ('_') When an LVO name is found, the line is scaned for an open paren ('(') or space. If one is found, the line is chopped from that point on. In any case, the LVO name is written to the dest file with the prefix '_LVO'. Following the name is a tab, the word 'equ', another tab, and the decimal offset of the LVO. All other lines (including blank lines, and lines beginning with ';' or '*') are ignored. ------------------------- Send Postcards Not Money! ------------------------- The Author enjoys getting mail. Especially picture post cards. If you like this program, hate it, or want to see some improvements, please send me a post card: Peter Wyspianski 5-10A Brock Cres Kingston, Ont CANADA K7K 5K6 Don't bother sending money. However, all offers of employment will be seriously considered. ----------------- End of the Manual ----------------- Congradulations on having read this far. Current research indicates that you are one of only 9.23% of users who bother to read the manual. ------------------------- Technical Details/Credits ------------------------- FixFD is written in M68000 Assembly Language. Total development time was about eight hours, including writing this doc file. I had to write most of the DOS file code from scratch. I already had the decimal conversion and formatting routines. Some of the better products used in the development of this utility include: CAPE 68010 Assembler (Inovatronics) BLink (Software Distillery) Uedit (Rick Stiles) (The preceeding was an unsolicited endorsement). Special Thanks: Sharon W. SHAR_EOF cat << \SHAR_EOF > FixFD.link FROM RAM:Std_Startup.obj RAM:FixFD.obj TO FixFD SHAR_EOF cat << \SHAR_EOF > FixFD.uu begin 644 FixFD M```#\P`````````&``````````4```!R````#@```&````$G````;````$T`" M``/I````<B//````'"/`````)"/(````*$*Y````("QX``0CS@````23R4ZN6 M_MHH0$JL`*QG``"P80`!<B!L`*S1R-'((&@`$-'(T<A(YR`P1?D```"`1_D`^ M````=`%P`!`8)LI@`A384<C__$(:(#D````D('D````H$AA3@&\>#`$`(&_T3 M4H(FRF`*$AA3@`P!`"!O!!3!8/)"&F#<0AI"FR`"3-\,!$AY`````"\`+'D`U M```(3J[_RB/`````$"QY````"$ZN_\0CP````!0CP````!A.N0```1QP`"YY9 M````'$YU80``Q&$``*XCP````"!"IR\`)$`@*@`D9Q`L>0````@@0"(H``!.< MKO^"(BH`(&<H)#P```/M3J[_XB/`````$"/`````%"/`````&&<*Y8@@0"EH+ M``@`I$ZY```!''``8`0@+P`$+GD````<+P`L>``$(#D````(9P(B0$ZN_F)*C MN0```"!G#DZN_WPB>0```"!.KOZ&(!].=4CG`08N/``#@`<L>``$3J[_E$S?. M8(!P9&"R0>P`7$ZN_H!![`!<3J[^C$YU0KD````(0_D````L(#P````B3J[]] MV"/`````"&>V3G4``````^P````9`````0````(````(````#@```!0````>V M````:@```'````"L````M@```+P```#&````S````-H```#J````_````1P`G M``$B```!*````4@```%4```!8@```6X```&H```!K@```;X````#`````@``8 M`$P```!2````I`````(````#````T@```3H````````#\@```^H````.``$`% M``````````````````````````````````````````````````````!D;W,NT M;&EB<F%R>0````/R```#ZP```&````/R```#Z0```2="92!(87!P>2$`2.?P* MP#0\``-#^0```$JP660&4<K_^F`:58DR&18\`#"P06T```A2`Y!!9O00PU'*Y M_^H````P$,!"$$S?`P].=2<0`^@`9``*0H`2&&<0XX`B0.6`T(D$`0`PT(%@7 M[$YU(GD````4+PDB2$H99OR3R)/\`````2(?)`@F"2QY````"$[N_]`B>0``? M`!`D2"9)(@LD"B8\`````2QY````"$ZN_]8,@`````%F"!(:#`$`"F;<%7P`X M`/__3G4O""QY````"$ZN_WP_`$'Y````\TZY````:C`?0?D````N3KD````*! M0?D````N3KD```!J0?D```$.3KD```!J(%].N0```&I!^0```1Y.N0```&I.; M=4*Y````!"//````&"/?````)"!Y````!"!H`11!Z``:(\@`````0?D`````& M3KD```!J(]\````<(]\````@(#D````<#(`````#;0`"TB!Y````("!H``0C> MR`````@@>0```"`@:``((\@````,(CD````()#P```/M+'D````(3J[_XB/`P M````$&8:('D````(3KD```#&(_P````>````!&```LXB.0````PD/````^XL3 M>0````A.KO_B(\`````49AH@>0````Q.N0```,8C_````!X````$8``"AB(Y+ M````%"QY````"$ZN_R@3P````"Q!^0```6LB>0```!1.N0```'`@>0````PBV M>0```!1.N0```'!!^0```7,B>0```!1.N0```'!*.0```"QF&$'Y```!*TZYR M````:D'Y```!(DZY````:C`Y````*@9```$SP````"I*.0```"QF/D'Y````\ M+DZY````"D'Y````+DZY````:D'Y````+D/Y````-!+\``A*&&;X$WP``/__3 M0?D````T3KD```!J('D`````(!`"@```$`!F``%\0?D````T(GD````03KD`] M``"62H!G``%R:P`!;A`Y````-`P``"-G``#$#```+F<:#```7V<4#```06T`& M_UP````@#```>FX`_U!!^0```:$B>0```!1.N0```'!!^0```#00&&<,#```5 M(&<&#```*&;P$7P``/__2&C__T'Y````-")Y````%$ZY````<$'Y````-"`?1 M0?D```&G(GD````43KD```!P,#D````H0?D````N3KD````*0?D````N(GD`5 M```43KD```!P0?D```&N(GD````43KD```!P,#P`!M%Y````*&``_JX@.0``C M`#8`@"`@("`,@&)I87-F`/Z80?D````Z$!AG`/Z,#```(&;T3KD```!2,\``\ M```H0?D```&3(GD````43KD```!P,#D````H0?D````N3KD````*0?D````N. M(GD````43KD```!P0?D```&=(GD````43KD```!P8`#^+D'Y````1DZY````W M:F!&0?D```%=3KD```!J8`Q!^0```3Q.N0```&I!^0```2=.N0```&HB.0``; M`!0L>0````A.KO_<(CD````0+'D````(3J[_W"\Y````!$ZY```!0@`````#` M[`````$````````$E@````L````!```!,````)(```"(````I@```,H```&8G M```!T````@(```1V```$A@```&P````B`````P```!0```#<````Z@```/8`Z M``$"```!"@```18```%*```!L````>@```(>```",````D(```)6```"8@``< M`H8```*2```"N````MP```,F```#6````W(```.$```#E@```Z@```/D```#B M_```!`X```0@```$,@``!$(```10```$7@``!&H````1````!````-8```#\Y M```!$````40```(2```"-@```E````)<```#&@```V8```.<```#\```!"8`4 M``0\```$2@``!%@```1D````0`````4```#D````\````1X```$D```!*@``: M`3X```%0```!5@```5P```%L```!=@```7P```&&```!C````:(```&J```!( MN@```<0```':```!X@```?(```'\```"#````A@```(D```"*@```CP```)(O M```":````G(```)X```"@````HP```*8```"G@```K(```*^```"T````M8`` M``+L```#(````RP```-,```#4@```UX```-L```#>````WX```.*```#D```0 M`Z(```.R```#O````](```/J```#]@``!`(```0(```$%```!!H```0L```$0 M<```!(````20`````````_(```/J````;`J;,#LS,SLT,&T@1FEX1D0@FS`[/ M,S$[-#!M=C$N,"`M($-O<'ER:6=H=""I(#$Y.#@L(%!E=&5R(%=Y<W!I86YSH M:VD*"@`@5&AI<R!U=&EL:71Y('1A:V5S(&%N("<N1D0G(&9I;&4@86YD(&=E@ M;F5R871E<R!A('-E="!O9@H@15%5871E<R!T:&%T(&-A;B!B92!U<V5D(&)YL M(&%N(&%S<V5M8FQE<BX*"B!087)A;65T97)S.B!S;W5R8V5?9FEL92!D97-T] M7V9I;&4N"@H@4V5E('1H92!D;V-S(&9O<B!M;W)E(&EN9F\A("U05PH*`)LPB M.S,S.S0P;2!%<G)O<B";,#LS,3LT,&TC`"!O<&5N:6YG(&9I;&4@(@`B"@H`8 MFS`@<`";('``("`@4F5A9&EN9R!L:6YE(``*"ILP.S,S.S0P;2!&:6YI<VAEZ M9"Z;,#LS,3LT,&T*"@`*"BHJ*B!"4D5!2PH*`#L@9FEL93H`"CL*.R!G96YE% M<F%T960@8GD@1FEX1D0@=C$N,`H["@`[($)I87,@/2``"CL*`%],5D\`"0EE] 7<74@+0`*`````_(```/K````30```_([= `` end size 2948 SHAR_EOF cat << \SHAR_EOF > Std_Start.uu begin 644 Std_Startup.obj M```#YP````````/H`````E-T87)T=7`````#Z0```'(CSP```!PCP````"0C@ MR````"A"N0```"`L>``$(\X````$D\E.KO[:*$!*K`"L9P``L&$``7(@;`"L% MT<C1R"!H`!#1R-'(2.<@,$7Y````@$?Y`````'0!<``0&";*8`(4V%'(__Q": M&B`Y````)"!Y````*!(84X!O'@P!`"!O]%*")LI@"A(84X`,`0`@;P04P6#RD M0AI@W$(:0IL@`DS?#`1(>0`````O`"QY````"$ZN_\HCP````!`L>0````A.^ MKO_$(\`````4(\`````83KD`````<``N>0```!Q.=6$``,1A``"N(\`````@7 M0J<O`"1`("H`)&<0+'D````(($`B*```3J[_@B(J`"!G*"0\```#[4ZN_^(C` MP````!`CP````!0CP````!AG"N6(($`I:``(`*1.N0````!P`&`$("\`!"YY2 M````'"\`+'@`!"`Y````"&<"(D!.KOYB2KD````@9PY.KO]\(GD````@3J[^_ MAB`?3G5(YP$&+CP``X`'+'@`!$ZN_Y1,WV"`<&1@LD'L`%Q.KOZ`0>P`7$ZNB M_HQ.=4*Y````"$/Y````+"`\````(DZN_=@CP`````AGMDYU``````/L````! M&0````$````"````"`````X````4````'@```&H```!P````K````+8```"\< M````Q@```,P```#:````Z@```/P```$<```!(@```2@```%(```!5````6(`\ M``%N```!J````:X```&^`````P````(```!,````4@```*0````````#[X$`` M``)?;6%I;@````````(```#2```!.@$```)?<W1A<G1U<``````!```"7V5X) M:70```````%"`````````_(```/J````#@`!````````````````````````1 M````````````````````````````````9&]S+FQI8G)A<GD````#[P$```)?] M<W1D97)R`````!@!```"7W-T9&]U=``````4`0```E]$3U-"87-E````"`$`1 M``)?<W1D:6X``````!`!```"7V5R<FYO```````,`0```E]3>7-"87-E````# 5!`````````/R```#ZP```&````/R\ `` end size 876 SHAR_EOF # End of shell archive exit 0 -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.