mirror of https://github.com/markpmlim/EdAsm.git
1 line
108 KiB
Plaintext
1 line
108 KiB
Plaintext
LINK_S_P1 PROC ORG $2000
|
|
; ### COMMENT - MACRO to create STR/.STRING directive equivalence.
|
|
; Remove this MACRO if the file M16.UTIL is ever INCLUDED.
|
|
MACRO
|
|
STR &string
|
|
LCLC &sset
|
|
&sset SETC &SETTING('STRING')
|
|
STRING PASCAL
|
|
DC.B &string
|
|
STRING &sset
|
|
MEND
|
|
; AsmIIGS directives to set equivalent 6502/65C02 mode.
|
|
MACHINE M6502
|
|
LONGA OFF
|
|
LONGI OFF
|
|
|
|
|
|
; This EdAsm/Asm816 source code file was converted to AsmIIGS
|
|
; by EdAsmCvtIIGS version 1.2 on 4/4/12 at 7:22:42 AM
|
|
|
|
INCLUDE 'equates.aii'
|
|
|
|
FileDataBufSiz EQU $2000-srcDataBuf ;20 mempages=5K
|
|
;
|
|
; Initial code disassembled with the ORCA.DisAsm
|
|
; Source files for the Linker is of type REL
|
|
; The Linker can produce BIN, REL or SYS object files
|
|
;
|
|
; Init the Linker
|
|
|
|
LinkerEntry
|
|
LDX #0
|
|
STX LinkerEntry ;Ensure a fresh copy is loaded
|
|
PHP ;Save status reg
|
|
PLA
|
|
STA SaveA
|
|
SEI ;Don't interrupts please
|
|
|
|
LDA #0
|
|
@loop STA STACK,X ;Zero 6502 H/W stack
|
|
INX
|
|
BNE @loop
|
|
|
|
DEX
|
|
TXS ;=$FF
|
|
LDA SaveA
|
|
PHA ;RESTORE status reg
|
|
PLP
|
|
|
|
LDA #$00
|
|
STA MINIVERS ;minimum interpreter version
|
|
LDA #$10
|
|
STA IVERSION ;interpreter version
|
|
LDA #%00000011 ;reserve Pages 6-7
|
|
STA MemoryMap
|
|
|
|
; setup memory map
|
|
|
|
LDA #%10101000
|
|
AND #%00000111
|
|
TAX ;(X)=0
|
|
|
|
LDY #0
|
|
TYA ;(A)=0
|
|
@loop1 ORA BitsTab,Y
|
|
INY
|
|
DEX
|
|
BPL @loop1
|
|
|
|
EOR #$FF ;(A)=%01111111
|
|
LDX #$15
|
|
AND MemoryMap,X ;Mark page $A8
|
|
STA MemoryMap,X ; as free
|
|
|
|
LDA #$00
|
|
DEX
|
|
@zloop STA MemoryMap,X ;Pages $08-$A7
|
|
DEX ; are free
|
|
BNE @zloop
|
|
|
|
; Init various flags & variables
|
|
|
|
LDA #$80 ;Set the following
|
|
STA MapOption ; options to ON
|
|
STA SortOption
|
|
STA XRefOption
|
|
STA EntryRefOption
|
|
|
|
LDA #$00 ;Set the following
|
|
STA PageOption ; options to OFF
|
|
STA Option_D ;reserved for future
|
|
STA IsOptions
|
|
STA WhichType
|
|
STA IsNumSort
|
|
STA Origin ;Zero this
|
|
STA Origin+1
|
|
|
|
LDA #1
|
|
STA LineCnt
|
|
STA PageCnt
|
|
|
|
; Try to open a default command (TXT) file named "EDASM.AUTOLINK"
|
|
|
|
LDY AUTOLNKS
|
|
@cploop LDA AUTOLNKS,Y
|
|
STA pathNameBuf,Y
|
|
DEY
|
|
BPL @cploop
|
|
|
|
JSR PRODOS8
|
|
DC.B $C8 ;OPEN
|
|
DC.W OpenCmdRecP8
|
|
BEQ DoPhase0
|
|
CMP #$46 ;fileNotFound?
|
|
BNE NoGood ;some other errors
|
|
BEQ FnotF
|
|
|
|
ShowErr JSR PrintError ;(A)=err code, don't come back
|
|
|
|
FnotF LDY #$00 ;Print Banner & prompt
|
|
JSR DisplayMsg ; for command filename
|
|
LDA #'?'+$80
|
|
STA PROMPT
|
|
JSR GetLine ;Use monitor's input rtn to get filename
|
|
STX pathNameBuf ;Save len byte
|
|
LDA InBuf ;Did user choose to Abort
|
|
CMP #CTRLC+$80 ; the linking process?
|
|
BNE @cloop2
|
|
JMP Abort ;Yes
|
|
|
|
@cloop2 LDA InBuf,X ;Copy the filename
|
|
AND #$7F ; typed in & ensure all
|
|
STA pathNameBuf+1,X ; its chars are std ASCII
|
|
DEX
|
|
BPL @cloop2
|
|
|
|
JSR PRODOS8
|
|
DC.B $C8 ;OPEN
|
|
DC.W OpenCmdRecP8
|
|
BEQ DoPhase0
|
|
|
|
CMP #$40 ;badPathSyntax
|
|
BEQ ShowErr
|
|
CMP #$44 ;pathNotFound
|
|
BEQ ShowErr
|
|
CMP #$45 ;volNotFound
|
|
BEQ ShowErr
|
|
CMP #$46 ;fileNotFound
|
|
BEQ ShowErr
|
|
|
|
NoGood JSR ErrHandler ;Don't come back
|
|
;=================================================
|
|
; Phase 0: Setup environment for the Linker
|
|
; Each record in the Command File is a CR-terminated text line (msb off)
|
|
; Each text line is either
|
|
; a command to the Linker or
|
|
; the pathname of a source file of type REL
|
|
; Directives/Commands to the Linker must be preceded by
|
|
; at least 1 space while pathnames have no leading space(s)
|
|
; ($20C7)
|
|
|
|
DoPhase0
|
|
LDA OpenCmdRecP8+C_OUTREF ;Copy this to the fields
|
|
STA MarkCmdRecP8+C_REFNUM ; of other ProDOS parameter
|
|
STA NewLineRecP8+C_REFNUM ; blocks b4 we start to read
|
|
STA ReadCmdRecP8+C_REFNUM ; the CMD file line by line
|
|
|
|
; Ensure that all future READ operations on the Command
|
|
; File is terminated by a CR or an EOF
|
|
|
|
JSR PRODOS8
|
|
DC.B $C9 ;NEWLINE
|
|
DC.W NewLineRecP8
|
|
BNE NoGood
|
|
|
|
LDA #BIN_type ;Default OBJECT filetype
|
|
STA TargetObjType
|
|
LDY #$03 ;Display "Phase0: Commands..."
|
|
JSR DisplayMsg
|
|
JSR DisplayCR
|
|
|
|
; This loop only processes directives & ignores the pathnames
|
|
|
|
@mainlp JSR AbortPause
|
|
JSR ReadOneCmd ;Is 1st char a CR/SPACE?
|
|
BNE NOTCMD ;No, it's a PN of a src (REL) file
|
|
JSR ShowLineBuf ;Show cmd
|
|
CMP #CR
|
|
BNE @1 ;1st char not CR => SPACE
|
|
JMP CmdFileErr ;CR => null cmd line
|
|
|
|
@1 JSR SkipSpaces
|
|
JSR ChkDirective ;Is it a directive?
|
|
BCS @mainlp ;Not valid, ignore
|
|
|
|
PHA ;index into JMP table
|
|
JSR WhiteSpc
|
|
JSR AdvCP ;Ensure cp is @ 1st char of directive
|
|
PLA
|
|
JSR HandleDirective ;Process directive
|
|
JMP @mainlp ;Next directive
|
|
|
|
; If 1st char is not CR/SPACE, then it is a pathname of a SRC file
|
|
|
|
NOTCMD BIT MapOption ;Output a LinkMAP? (default is ON)
|
|
BPL @exit ;No
|
|
JSR OpenLinkMap ;Open LINKMAP file for output
|
|
@exit JMP DoPhase1
|
|
;=================================================
|
|
; JMP via an RTS to parse the operand field of a directive
|
|
|
|
HandleDirective
|
|
TAX
|
|
LDA CmdTabHi,X ;Directive JMP table
|
|
PHA
|
|
LDA CmdTabLo,X
|
|
PHA
|
|
RTS
|
|
;=================================================
|
|
; BIN command/directive
|
|
; Input
|
|
; WhichType=0 OBJECT file type not set
|
|
; Output
|
|
; WhichType=1
|
|
; TrgtFTyp=BIN
|
|
; NB. Only one BIN/REL/SYS directive may be declared
|
|
|
|
CmdBIN LDA WhichType ;Has the OBJ type been set?
|
|
BEQ @1 ;No
|
|
JMP DupCmdErr
|
|
|
|
@1 LDA #$01
|
|
STA WhichType ;Flag it's set
|
|
LDA #BIN_type
|
|
STA TargetObjType
|
|
JSR GetObjPathName ;Get Link OBJ/MAP filenames
|
|
RTS
|
|
;=================================================
|
|
; REL command/directive
|
|
; Input
|
|
; WhichType=0
|
|
; Output
|
|
; WhichType=$80
|
|
; TrgtFTyp=REL
|
|
|
|
|
|
CmdREL LDA WhichType
|
|
BEQ @1
|
|
JMP DupCmdErr
|
|
|
|
@1 LDA #$80
|
|
STA WhichType
|
|
LDA #REL_type
|
|
STA TargetObjType
|
|
JSR GetObjPathName
|
|
RTS
|
|
;=================================================
|
|
; SYS command/directive
|
|
; Input
|
|
; WhichType=0
|
|
; Output
|
|
; WhichType=$02
|
|
; TrgtFTyp=SYS
|
|
|
|
CmdSYS LDA WhichType
|
|
BEQ @1
|
|
JMP DupCmdErr
|
|
@1 LDA #$02
|
|
STA WhichType
|
|
LDA #SYS_type
|
|
STA TargetObjType
|
|
JSR GetObjPathName
|
|
RTS
|
|
;=================================================
|
|
; ORG command/directive
|
|
; Input
|
|
; Output
|
|
; Origin=Value of Expression
|
|
; NB. Only 1 ORG may be declared and it must be b4
|
|
; any SRC pathnames
|
|
|
|
CmdORG LDA Origin ;Already set?
|
|
ORA Origin+1
|
|
BEQ @1
|
|
JMP DupCmdErr ;Yes -> duplicate cmd
|
|
|
|
@1 JSR SkipSpaces
|
|
JSR ChrGot
|
|
BEQ BADORG ;if sp/cr, error
|
|
JSR EvalExpr
|
|
LDA Value16 ;Chk it's valid
|
|
STA Origin
|
|
LDA Value16+1
|
|
BEQ BADORG ;if < $0100
|
|
STA Origin+1
|
|
ORA Origin
|
|
BEQ BADORG ; or $0000
|
|
RTS
|
|
BADORG JMP CmdSynErr ;syntax err
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; ALN Command/Directive
|
|
; Align Origin @ start of next mempage
|
|
; Output
|
|
; Origin=$xx00
|
|
;
|
|
; This directive is usually used after a pathname
|
|
; and may be used repeatedly
|
|
;
|
|
|
|
CmdALN LDA Origin ;ORG must be set first either by a
|
|
ORA Origin+1 ; directive or via SRC file
|
|
BNE @1
|
|
JMP WrongOrder ;Wrong cmd order
|
|
|
|
@1 LDA Origin ;Align @ the beginning
|
|
BEQ @exit
|
|
INC Origin+1 ; of the next mempage
|
|
LDA #$00
|
|
STA Origin
|
|
@exit RTS
|
|
;=================================================
|
|
; OPT command/directive. Only allowed to be used once
|
|
; Default
|
|
; OPT +M,+E,+S,+X,-N,-D,-P
|
|
; Input
|
|
; IsOptions
|
|
; Output
|
|
; IsOptions=1 - If Directive not declared
|
|
;
|
|
; One/Some/All of the following flags may be set
|
|
; M)apFile - Output LinkMAP file (default ON)
|
|
; E)Ref - Add ENTRY records (default ON)
|
|
; S)ortLM - Sort LoadMap table (default ON)
|
|
; X)Ref - Cross-referenced (default ON)
|
|
; N)umSort - Sort LoadMap numerically (default OFF)
|
|
; O)ptD - not used (default OFF)
|
|
; P)age - Pagination (default OFF)
|
|
; ($21A4)
|
|
|
|
CmdOptions
|
|
LDA IsOptions ;First time the directive is declared?
|
|
BEQ @1 ;Yes
|
|
JMP DupCmdErr ;Duplicate cmd
|
|
|
|
@1 INC IsOptions ;Flag we have encountered this cmd
|
|
JSR SkipSpaces ;Prepare to look at the operand field
|
|
|
|
@doloop JSR ChrGot
|
|
BEQ @ret ;cr/space
|
|
CMP #'+' ;ON switch flag?
|
|
BNE @off ;No
|
|
LDA #$80
|
|
STA SWITCH ;flag it is ON
|
|
BNE @which ;always
|
|
|
|
@off CMP #'-'
|
|
BNE @bad
|
|
|
|
LDA #$00 ;OFF
|
|
STA SWITCH
|
|
@which JSR ChrGet ;Get char after switch flag
|
|
BEQ @bad ;It's a cr/space
|
|
LDX #0
|
|
@cmplup CMP OptionsTab,X
|
|
BEQ @gothit
|
|
INX
|
|
CPX #7
|
|
BCC @cmplup
|
|
@bad JMP OptionError ;Invalid option/option syntax
|
|
|
|
@gothit LDA SWITCH
|
|
STA OptFlagsTab,X ;$A2-$A8
|
|
@skip JSR ChrGet ;Get char
|
|
BEQ @ret ;cr/space
|
|
CMP #',' ;delimiter
|
|
BNE @skip ;ignore all others
|
|
INY ;SKIP comma
|
|
JMP @doloop ;Loop back for another option
|
|
@ret RTS
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Parse for the pathnames of the OBJ file and LINKMAP txt file.
|
|
; Full and partial pathnames are accepted. If there is no
|
|
; operand field following the BIN/REL/SYS directive/cmd then
|
|
; default filenames are used.
|
|
;
|
|
; Output
|
|
; LinkObjName buf
|
|
; ($21ED)
|
|
|
|
GetObjPathName
|
|
JSR SkipSpaces
|
|
@cloop JSR ChrGot
|
|
BEQ @ws ;cr/space
|
|
JSR ChkChar ;Is char valid?
|
|
BNE @1 ;No
|
|
INY
|
|
STA LinkObjName,Y
|
|
BNE @cloop
|
|
|
|
@1 CMP #CR ;Is it a CR?
|
|
@ws PHP ;save comparison status
|
|
CPY #0 ;Is there an operand?
|
|
BEQ @2 ;No
|
|
STY LinkObjName ;Len byte
|
|
@2 PLP
|
|
BEQ @ret ;Yes, it's a CR, so done
|
|
CMP #',' ;Check for the delimiter
|
|
BNE @FnotF ;Not found
|
|
|
|
LDX #0
|
|
INY ;SKIP the comma
|
|
@sloop JSR ChrGot
|
|
BEQ @gotws ;cr/space
|
|
JSR ChkChar ;Is char valid?
|
|
BNE @FnotF ;No, err
|
|
INX
|
|
INY
|
|
STA LinkMapName,X
|
|
BNE @sloop
|
|
|
|
@gotws CPX #0 ;If no user-defined LINKMAP file,
|
|
BEQ @ret ; specified use default name
|
|
STX LinkMapName ;Len byte
|
|
@ret RTS
|
|
|
|
@FnotF LDA #$40 ;badPathSyntax
|
|
JSR ErrHandler ;Don't come back
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Check if a char is valid
|
|
; Valid chars are: / . 0-9 A-Z
|
|
; Input
|
|
; (A)=ascii char
|
|
; Output
|
|
; Z=1 if char is valid
|
|
; ($2232)
|
|
|
|
ChkChar
|
|
CMP #'/'
|
|
BEQ @ret
|
|
CMP #'.'
|
|
BEQ @ret
|
|
JSR IsCharDec ;Is it a decimal digit?
|
|
BCC @valid ;Yes
|
|
CMP #'A'
|
|
BCC @ret
|
|
CMP #'Z'+1
|
|
BCC @valid
|
|
CMP #'A'
|
|
RTS
|
|
@valid STA PROMPT
|
|
CMP PROMPT ;Ensure Z=1
|
|
@ret RTS
|
|
;=================================================
|
|
; Copy default OBJECT file name to the PathName buf
|
|
; ($224F)
|
|
|
|
MoveObjName
|
|
LDY LinkObjName
|
|
@mvLup LDA LinkObjName,Y
|
|
STA pathNameBuf,Y
|
|
DEY
|
|
BPL @mvLup
|
|
RTS
|
|
;===============================
|
|
; Copy default LINKMAP file name to the PathName buf
|
|
; ($225C)
|
|
|
|
MoveMapName
|
|
LDY LinkMapName
|
|
@mvLup2 LDA LinkMapName,Y
|
|
STA pathNameBuf,Y
|
|
DEY
|
|
BPL @mvLup2
|
|
RTS
|
|
;===============================
|
|
; Open for new LINKMAP text file for writing
|
|
; Input
|
|
; Output
|
|
; ($2269)
|
|
|
|
OpenLinkMap
|
|
JSR MoveMapName ;Set PN to LINKMAP's
|
|
JSR PRODOS8 ;Kill the old copy (if any)
|
|
DC.B $C1
|
|
DC.W DestroyRecP8 ;DESTROY
|
|
|
|
JSR PRODOS8
|
|
DC.B $C0 ;CREATE
|
|
DC.W CreateMapRecP8
|
|
BNE @Err
|
|
|
|
JSR PRODOS8
|
|
DC.B $C8 ;OPEN
|
|
DC.W Open2RecP8
|
|
BEQ @NoErrs
|
|
@Err JSR ErrHandler ;Don't come back
|
|
|
|
@NoErrs LDA Open2RecP8+C_OUTREF
|
|
STA WriteMapRecP8+C_REFNUM
|
|
LDA #0
|
|
STA MapIndex ;Double as # of bytes to write
|
|
STA MapIndex+1 ;HOB=Always 0
|
|
RTS
|
|
;=================================================
|
|
; Using info fr the ESD (if any) of the SRC files,
|
|
; build 3 arrays called ENTRY, EXTRN & SymbolicName tables.
|
|
; entRecP - Point to an element of the ENTRY table of 24-byte records
|
|
; xtrnRecP - Point to an element of the EXTRN table of 8-byte records
|
|
; symP - Point to an element of the SymbolicName table of 16-byte records
|
|
; ModuleNbr - src file # assigned during processing
|
|
; CurrORG - starting PC of current src file
|
|
; ($2294)
|
|
|
|
DoPhase1
|
|
LDY #$04 ;Building ENTRY/EXTERN tables
|
|
JSR DisplayMsg
|
|
JSR DisplayCR
|
|
LDY #$04
|
|
JSR StoreMsgY ;Store same msg to LINKMAP
|
|
|
|
LDA #<EntryTab
|
|
STA entRecP ;array of ENTRY recs @ $4700
|
|
LDA #>EntryTab
|
|
STA entRecP+1
|
|
LDA #<xternTab ;array of XTRN recs @ $7100
|
|
STA xtrnRecP
|
|
LDA #>xternTab
|
|
STA xtrnRecP+1
|
|
LDA #<symbolTab ;array of SymbolicName recs @ $9200
|
|
STA symP
|
|
LDA #>symbolTab
|
|
STA symP+1
|
|
|
|
LDA #0
|
|
STA ModuleNbr ;start w/module 0
|
|
LDA Origin
|
|
STA CurrORG
|
|
LDA Origin+1
|
|
STA CurrORG+1
|
|
JMP Phs11
|
|
|
|
; Process a SRC file. The only directive allowed
|
|
; is ALN which instructs the Linker to adjust
|
|
; the PC to the start of next mem page
|
|
|
|
Phs1Loop
|
|
JSR AbortPause
|
|
JSR ReadOneCmd
|
|
BNE Phs11 ;Not a cr/space => we've a PN
|
|
CMP #CR
|
|
BEQ GoPhase2 ;Empty line -> no more cmds
|
|
JSR IsAlign ;Is it an ALN directive?
|
|
BCC @1 ;Yes -> align mem
|
|
JMP DoBreak ;Abort!
|
|
|
|
@1 BEQ @2 ;ALN option
|
|
JMP WrongOrder ;No, invalid cmd order
|
|
|
|
@2 LDA CurrORG ;Already @ a mempage bdry?
|
|
BEQ Phs1Loop ;Yes
|
|
INC CurrORG+1 ;Next mempage
|
|
LDA #$00
|
|
STA CurrORG
|
|
BEQ Phs1Loop ;always
|
|
|
|
GoPhase2 JMP DoPhase2
|
|
|
|
; The name of a SRC file is already in CmdLine buffer
|
|
; Open the SRC file and setup some variables
|
|
; using the info fr the opened SRC file.
|
|
;
|
|
; CmdLineBuf - Pathname of SRC file
|
|
; entRecP - ptr to a rec of ENTRY array
|
|
; xtrnRecP - ptr to a rec of EXTRN array
|
|
; symP - ptr to a rec of SymbolicName array
|
|
;
|
|
; Origin - ORG of 1st SRC file (if not) set by an ORG directive
|
|
; CurrORG - Starting PC assigned to curr SRC file
|
|
; MarkSrcRecP8+c.mark - file posn of source file
|
|
; srcP - pointer into a chunk of source file
|
|
;
|
|
; Z80 - End of chunk of RLD data read
|
|
; Z82 - Start of RLD data read
|
|
|
|
Phs11 JSR ShowLineBuf
|
|
JSR OpenSrcFile ;Open SRC file and get info
|
|
BCC Phs12
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
Phs12 LDA Origin ;Was it set?
|
|
ORA Origin+1
|
|
BNE ORGset ;Yes
|
|
|
|
LDA srcORG ;Use the ORG as recorded
|
|
STA Origin ; in the FIRST SRC file
|
|
STA CurrORG ; as our Origin & use it as
|
|
LDA srcORG+1 ; the starting PC as well
|
|
STA Origin+1 ;NB. Once set, it will remain unchanged
|
|
STA CurrORG+1 ; throughout linking process
|
|
|
|
ORGset LDA #2
|
|
CLC
|
|
ADC srcCodeLen ;Len of code image
|
|
STA MarkSrcRecP8+C_MARK ;Set file posn to SRC file's
|
|
LDA #0 ; relocation dictionary (RLD)
|
|
ADC srcCodeLen+1
|
|
STA MarkSrcRecP8+C_MARK+1 ; which is just after the code image
|
|
LDA OpenSrcRecP8+C_OUTREF
|
|
STA MarkSrcRecP8+C_REFNUM
|
|
JSR PRODOS8
|
|
DC.B $CE ;SET_MARK
|
|
DC.W MarkSrcRecP8
|
|
BNE GotErr2
|
|
|
|
JSR ReadMax ;Read max chunk of RLD/ESD
|
|
BCC FinalData ;=> The entire RLD/ESD was read
|
|
CMP #$10 ;Did we encounter an EOF?
|
|
BEQ MoreData ;No, more data chunks
|
|
GotErr2 JSR ErrHandler ;(A)=$4C, so let EI takes care of it
|
|
|
|
; A fixed chunk (of 5K) had been read so there may be more
|
|
; data to be read. There seems to be no provision dealing
|
|
; with files in which the END of RLD is not within
|
|
; the first 5K of RLD/ESD data i.e. the RLD is very big.
|
|
; The code below doesn't seem to be able to handle this
|
|
; situation. Is there a bug here?
|
|
; The code below will never be executed if sizeof RLD+ESD < 5K
|
|
|
|
MoreData
|
|
JSR GetEndRLD ;Scan for end of RLD
|
|
LDA srcP+1 ;Is srcP still at the BO
|
|
CMP #>srcDataBuf ; the srcfile data buffer?
|
|
BNE SizeChk ;No
|
|
LDA srcP ;(Shouldn't srcP be compared to $2000?)
|
|
CMP #<srcDataBuf ; which is EO srcDataBuf+1
|
|
BNE SizeChk
|
|
BigESD JMP RLDESDErr ;SRC file's ESD too large
|
|
|
|
; This code is only executed if the size of the RLD is less
|
|
; than the size of the srcDataBuf located @ $0C00 (which is 5K)
|
|
; srcP is pointing @ EO RLD
|
|
|
|
SizeChk LDA #<srcDataBuf ;START addr
|
|
CLC
|
|
ADC RWFileRecP8+C_TRANSCNT ;Actual # of bytes read
|
|
STA Z80 ;Point @ EO data chunk + 1
|
|
LDA #>srcDataBuf
|
|
ADC RWFileRecP8+C_TRANSCNT+1 ; (or EO file data buf + 1=$2000)
|
|
STA Z80+1 ;END addr
|
|
|
|
LDA #<srcDataBuf
|
|
STA Z82 ;DEST addr
|
|
LDA #>srcDataBuf
|
|
STA Z82+1
|
|
|
|
; Calc the size of ESD data in FileData buf
|
|
; The code below is definitely buggy.
|
|
|
|
LDA Z80
|
|
SEC
|
|
SBC srcP ;Pointing @ EO RLD
|
|
STA RWFileRecP8+C_TRANSCNT ;=len of ESD already in buf + 1 (EO RLD marker)
|
|
LDA Z80+1 ;(should srcP be incr 1 more?)
|
|
SBC srcP+1
|
|
STA RWFileRecP8+C_TRANSCNT ;Bug! Should be sta RWFileRecP8+c.transCnt+1
|
|
|
|
; Move ESD block forward in filedata buf (incl EO RLD marker)
|
|
|
|
JSR MoveData
|
|
LDA #<srcDataBuf ;Prepare to append more ESD data
|
|
CLC
|
|
ADC RWFileRecP8+C_TRANSCNT ; fr src file by reading 'em
|
|
STA RWFileRecP8+C_DATABUF ; into this starting location
|
|
LDA #>srcDataBuf
|
|
ADC RWFileRecP8+C_TRANSCNT ;Bug! Should be adc RWFileRecP8+c.transCnt+1
|
|
STA RWFileRecP8+C_DATABUF+1
|
|
|
|
; Calculate # of bytes to be read in
|
|
; order to fill the rest of FileData
|
|
; buf with more ESD records
|
|
|
|
LDA #<FileDataBufSiz
|
|
SEC
|
|
SBC RWFileRecP8+C_TRANSCNT
|
|
STA RWFileRecP8+C_REQCNT ;=$1400-(# of bytes of
|
|
LDA #>FileDataBufSiz
|
|
SBC RWFileRecP8+C_TRANSCNT+1 ; data currently in mem)
|
|
STA RWFileRecP8+C_REQCNT+1
|
|
JSR GetMoreCode ;Attempt to read another chunk
|
|
BCC FinalData ;Last chunk so that's ok
|
|
CMP #$10 ;More data on disk?
|
|
BEQ BigESD ;Yes, ESD too large
|
|
BNE GotErr2 ;Always-error
|
|
|
|
; Last chunk of RLD/ESD data had been read
|
|
; The code below seems ok
|
|
|
|
FinalData
|
|
JSR GetEndRLD ;Point to end of RLD
|
|
LDA OpenSrcRecP8+C_OUTREF
|
|
JSR CloseAnyFile ;Close SRC file
|
|
INC srcP ;Skip the EO RLD marker which
|
|
BNE BUMP1 ; is a $00 to point @ appended ESD
|
|
INC srcP+1
|
|
|
|
BUMP1 LDY ModuleNbr ;Current file module #
|
|
LDA xtrnRecP ;Ptr to 1st EXTRN record
|
|
STA srcModTabLo,Y ; for this module
|
|
LDA xtrnRecP+1
|
|
STA srcModTabHi,Y
|
|
|
|
; Add records to the Symbol, ENTRY/EXTRN
|
|
; tables using information from an ESD record.
|
|
; Careful note should be paid to the fact
|
|
; that an ENTRY record & a Symbol record has the
|
|
; same data in their respective first field.
|
|
|
|
ScanESD
|
|
JSR AbortPause
|
|
LDY #Str15.sizeof-1 ;FOR Y= 15 to 1
|
|
LDA #SPACE
|
|
@bloop STA (entRecP),Y
|
|
STA (symP),Y
|
|
DEY
|
|
BNE @bloop
|
|
|
|
; Y=0 on fall thru
|
|
; NB: All chars of symbolic name record will have their msb off.
|
|
; The SymbolicName record is a p-string (likely to be a
|
|
; truncation of the original symbolic name in ESD)
|
|
|
|
MakeRecords
|
|
LDA (srcP),Y ;Get 1st char of symbolic name
|
|
BNE @1
|
|
JMP DoneESD ;EO ESD => Done processing this file
|
|
@1 PHP ;save status of its msb
|
|
AND #$7F
|
|
INY
|
|
STA (entRecP),Y ;Copy the char to both ENTRY and
|
|
STA (symP),Y ; SymbolicName records
|
|
PLP ;Is its msb off?
|
|
BPL CheckSymType ;Yes, last char of symbolic name
|
|
CPY #Str15.sizeof-1 ;max len of linker symbol
|
|
BCC MakeRecords ;Next char
|
|
|
|
; Only the first 15 chars are copied. We skip the rest of chars.
|
|
; However, we still need to locate the eo the symbolicname
|
|
; in order to get @ the symbol-type flag etc.
|
|
|
|
@sloop LDA (srcP),Y ;Get symbolicname's char
|
|
INY
|
|
TAX ;Is this the last char?
|
|
BMI @sloop ;No
|
|
|
|
CheckSymType
|
|
TYA ;(Y)=index symbol-type flag byte
|
|
LDY #EntryRecord.symbolName
|
|
STA (entRecP),Y ;Set the len byte of symbolName
|
|
STA (symP),Y ; fields of both recs
|
|
TAY
|
|
LDA (srcP),Y
|
|
STA ESDWrkRec+ESDRecord.flags
|
|
|
|
; The next 2 fields depends on the symbol type above.
|
|
; If symbol is flagged as EXTRN, first field is the symbol
|
|
; # referred to by an RLD entry. The 2nd field must be zero.
|
|
; If symbol is flagged as ENTRY, they are the 2 bytes of
|
|
; relocateable address.
|
|
|
|
INY
|
|
LDA (srcP),Y
|
|
STA ESDWrkRec+ESDRecord.externNum ;or ESDRecord.relAddr
|
|
INY
|
|
LDA (srcP),Y
|
|
STA ESDWrkRec+ESDRecord.unused
|
|
|
|
LDA ESDWrkRec+ESDRecord.flags
|
|
AND #entry ;Is it an ENTRY symbol-type?
|
|
BNE DoEntry ;Yes
|
|
|
|
LDX #xtrnRecP
|
|
BIT Z9E ;Include code fr this file?
|
|
BPL DoXtrn ;Yes
|
|
JMP NxtEntryZ ;No recs will be added to the 3 tables
|
|
|
|
;================================================
|
|
; Process an EXTRN symbol-type rec in ESD of a src file
|
|
|
|
DoXtrn LDA #0 ;Zero the curr ENTRY slot
|
|
LDY #EntryRecord.sizeof
|
|
@zloop STA (entRecP),Y ; which had been partially
|
|
DEY ; filled with the symbolicname
|
|
BPL @zloop
|
|
|
|
; Create a EXTRN record in table @ $7100
|
|
; Each record is 8 bytes
|
|
; Initial Layout of each record is as follows:
|
|
; offset Description
|
|
; 0 DW ptr to a record in SymbolicName table ($9200) or
|
|
; ptr to another EXTRN rec if the SymbolicName
|
|
; matched with that in one of the ENTRY recs
|
|
; 2 DW Ptr to an ENTRY record; NULL initially
|
|
; 4 DB file # of SRC file (also called module #)
|
|
; 5 DB FlagByte
|
|
; 6 DB symbol # referred to by an RLD record
|
|
; 7 DB 0
|
|
|
|
; First we assume the symbol name is not in the Symbol table
|
|
; by setting first field to point to the new symbolic name record
|
|
; which had not been "added" to the its table.
|
|
|
|
LDY #XtrnRecord.symNamePtr ;XtrnRecord.next?
|
|
LDA symP
|
|
STA (xtrnRecP),Y ;Point to the new record of
|
|
LDA symP+1 ; Symbol table @ $9200
|
|
INY
|
|
STA (xtrnRecP),Y
|
|
INY ;=2
|
|
|
|
LDA #NULL
|
|
STA (xtrnRecP),Y ;XtrnRecord.entryPtr = NULL
|
|
INY
|
|
STA (xtrnRecP),Y
|
|
INY ;=4
|
|
|
|
LDA ModuleNbr
|
|
STA (xtrnRecP),Y ;XtrnRecord.fileNum = file # of the SRC file
|
|
LDA ESDWrkRec+ESDRecord.flags
|
|
ORA #undefined+unreferenced
|
|
INY ;=5
|
|
|
|
STA (xtrnRecP),Y ;XtrnRecord.flags
|
|
INY ;=6
|
|
|
|
LDA ESDWrkRec+ESDRecord.externNum
|
|
STA (xtrnRecP),Y ;Symbol # referred to by an RLD record
|
|
INY ;=7
|
|
|
|
LDA #$00
|
|
STA (xtrnRecP),Y ;ESDRecord.unused = 0;
|
|
JSR ScanEntryTable ;Is this symbol already in ENTRY table?
|
|
BNE CHKSYMTBL ;No
|
|
JSR AppendNode ;Yes, add this EXTRN rec to singly-linked list
|
|
JMP DoneXtrn ;Add this EXTRN rec to its table
|
|
|
|
CHKSYMTBL
|
|
JSR ScanSymbolTab ;Is symbol already in SymbolicName table?
|
|
BNE AddSymbolTab ;No => add the newly-built Symbol rec to its table
|
|
|
|
; The symbolic name is already in the Symbol table so we have
|
|
; to change the first field of the XTRN record to point
|
|
; to the "found" record.
|
|
|
|
LDY #XtrnRecord.next ;XtrnRecord.symNamePtr
|
|
LDA Z88 ;Set this link to point
|
|
STA (xtrnRecP),Y ; to SymbolicName record that is
|
|
INY
|
|
LDA Z88+1 ; already in Symbol array
|
|
STA (xtrnRecP),Y
|
|
JMP DoneXtrn ;Don't add newly-built Symbol rec to its table
|
|
|
|
; We are extending the Symbol table by one record.
|
|
; This is done by incrementing symP by the appropiate
|
|
; # of bytes i.e. symP++ (in C Syntax)
|
|
|
|
AddSymbolTab
|
|
JSR AdvNxtSymbol ;Adv to next empty slot of SymbolicName array
|
|
LDA symP+1 ;Can we extend the SymbolicName array further?
|
|
CMP #>XA8E0 ;(Linker's HiMem is set @ $A8E0)
|
|
BCC DoneXtrn
|
|
BNE @full
|
|
LDA symP
|
|
CMP #<XA8E0
|
|
BCC DoneXtrn
|
|
@full JMP SymbolTabFull ;Yes
|
|
|
|
; Do a XtnP++ to point @ the next empty slot in EXTRN array
|
|
|
|
DoneXtrn
|
|
JSR AdvNxtExtrn
|
|
JMP NxtEntryZ ;Prepare to process next rec in appended ESD
|
|
|
|
;================================================
|
|
; Process an ENTRY symbol-type record in ESD of src file
|
|
; The 1st field is already done
|
|
; Layout of 24-byte records in ENTRY table @ $4700
|
|
; offset
|
|
; 0 STR up to 16 chars including len byte
|
|
; 16 DB file # of src file (start fr 0)
|
|
; 17 DB symbol-type
|
|
; 18 DW relocated addr
|
|
; 20 DW 0 (Ptr to EXTRN record) - first/head
|
|
; 22 DW 0 (Ptr to EXTRN record) - last/tail
|
|
|
|
; When control is transferred here, the 2nd field
|
|
; of the ESDRecord is a 2-byte offset wrt the SRC
|
|
; file's recorded ORG
|
|
|
|
DoEntry BIT Z9E ;Include code fr this file?
|
|
BMI DOENTRY1 ;No
|
|
|
|
LDA ESDWrkRec+ESDRecord.relAddr+1
|
|
CMP srcORG+1 ;Origin as recorded in SRC file
|
|
BCC DOENTRY1
|
|
LDA objCurrSize+1 ;addr+1 of last byte of code image
|
|
SEC
|
|
SBC ESDWrkRec+ESDRecord.relAddr+1
|
|
BMI DOENTRY1 ;Is addr to be relocated btwn
|
|
BNE CalcAddr ; addrs of 1st & last byte of image?
|
|
LDA ESDWrkRec+ESDRecord.relAddr
|
|
CMP objCurrSize
|
|
BCS DOENTRY1 ;Out of range
|
|
|
|
; Calc relocated addr of the instruction
|
|
; First do an equivalent to a subtraction
|
|
; to obtain the instruction' offset wrt
|
|
; the src file's Origin
|
|
|
|
CalcAddr
|
|
;Do a 2's complement of SRC file's Origin
|
|
LDA ESDWrkRec+ESDRecord.relAddr
|
|
CLC
|
|
ADC NegSrcORG
|
|
STA ESDWrkRec+ESDRecord.relAddr
|
|
LDA ESDWrkRec+ESDRecord.relAddr+1
|
|
ADC NegSrcORG+1
|
|
STA ESDWrkRec+ESDRecord.relAddr+1
|
|
|
|
;Calc the relocated addr
|
|
|
|
LDA ESDWrkRec+ESDRecord.relAddr
|
|
CLC
|
|
ADC CurrORG
|
|
STA ESDWrkRec+ESDRecord.relAddr
|
|
LDA ESDWrkRec+ESDRecord.relAddr+1
|
|
ADC CurrORG+1
|
|
STA ESDWrkRec+ESDRecord.relAddr+1
|
|
|
|
DOENTRY1
|
|
LDY #EntryRecord.fileNum
|
|
LDA ModuleNbr ;SRC file #
|
|
STA (entRecP),Y
|
|
INY
|
|
LDA ESDWrkRec+ESDRecord.flags
|
|
ORA #unreferenced ;This is a new record which has ($40)
|
|
STA (entRecP),Y ; yet to be referenced
|
|
INY
|
|
LDA ESDWrkRec+ESDRecord.relAddr
|
|
STA (entRecP),Y
|
|
INY
|
|
LDA ESDWrkRec+ESDRecord.relAddr+1
|
|
STA (entRecP),Y
|
|
|
|
LDA #NULL ;FOR Y=20 TO 23
|
|
@zloop INY
|
|
CPY #EntryRecord.sizeof
|
|
STA (entRecP),Y ;Set both links to NULL as well
|
|
BCC @zloop
|
|
|
|
LDY #0
|
|
TYA ;Zero len byte so that the scanning
|
|
STA (entRecP),Y ; below will skip this ENTRY rec
|
|
JSR ScanEntryTable ;Is this symbol already in ENTRY table?
|
|
PHP ;save for later
|
|
LDA (symP),Y ;Get a copy of len byte from Symbol record
|
|
STA (entRecP),Y ; & restore to ENTRY record (NB. Y=0)
|
|
PLP
|
|
BNE NxtEntry ;Not in ENTRY table
|
|
JSR StoreDupSym ;Record duplicate symbol
|
|
|
|
; Do a EntP++ to point @ the next empty slot in ENTRY table
|
|
|
|
NxtEntry
|
|
JSR AdvNxtEntry
|
|
; ($2502)
|
|
NxtEntryZ
|
|
JSR NxtESDRec ;Point @ next rec in appended ESD
|
|
LDA $01,X ;Since (X)=$8A,$8C, the locations
|
|
CMP GoShowMsgZ,X ; $360D+$8A/$8C=$3697/$3699 are accessed
|
|
BEQ SymbolTabFull ;($3697)=$60 and ($3699)=$00; bug?
|
|
JMP ScanESD ;Loop back to process the ESD record
|
|
|
|
SymbolTabFull
|
|
LDY #$0A ;Report "symbol table is full"
|
|
JSR GoShowMsg
|
|
|
|
; We have finishing processing the ESD of the curr file.
|
|
; Do some housekeeping b4 processing the next file.
|
|
; NB. If a SRC pathname is preceded by an asterik,
|
|
; its SymbolicNames will be referenced but no
|
|
; object code will be incorporated into the
|
|
; final OBJ file.
|
|
|
|
DoneESD
|
|
BIT Z9E ;Was SRC PN preceded by a *?
|
|
BMI NxtSrc ;Yes => its code will not be incorporated in OBJ file
|
|
|
|
LDA srcCodeLen
|
|
CLC
|
|
ADC CurrORG ;Starting PC for
|
|
STA CurrORG ; the next SRC file
|
|
LDA srcCodeLen+1
|
|
ADC CurrORG+1
|
|
STA CurrORG+1
|
|
|
|
NxtSrc INC ModuleNbr
|
|
LDA ModuleNbr
|
|
CMP #maxSrcFiles
|
|
BCS TooMany
|
|
JMP Phs1Loop ;Process next SRC file
|
|
|
|
TooMany LDY #$0B ;Report "Too many SRC files"
|
|
JSR GoShowMsg
|
|
;=================================================
|
|
; Get the end of Relocation Dictionary of the SRC file
|
|
; Each record in the Relocation Dictionary is 4 bytes long
|
|
; Input
|
|
; srcP - ptr to beginning of an RLD chunk
|
|
; Output
|
|
; (Y)=0
|
|
; srcP - End of RLD if found
|
|
; Z=1
|
|
; X - not used
|
|
;
|
|
; Possible bug here. The code should check that srcP
|
|
; should not exceed upper limit of srcDataBuf which is
|
|
; $2000 unless it's assumed that RLD is always < 5K. For
|
|
; such cases, since each RLD record is 4 bytes, the max #
|
|
; of RLD records in a SRC file = (5x1024)/4 -1 = 1279
|
|
; This rtn should be re-written to handle files with huge RLDs
|
|
; When the end of the RLD is not found, it should check that
|
|
; srcP == (srcDataBuf+FileDataBufSiz) by returning a flag to
|
|
; the caller.
|
|
; ($2539)
|
|
|
|
GetEndRLD
|
|
LDY #0
|
|
@scan1 LDA (srcP),Y ;Get RLD-flag byte
|
|
AND #%00000001 ;Is it EO RLD?
|
|
BEQ @done ;Yes
|
|
LDA #RLDRecord.sizeof ;Point @ next RLD record
|
|
CLC
|
|
ADC srcP
|
|
STA srcP
|
|
LDA #0
|
|
ADC srcP+1
|
|
STA srcP+1
|
|
JMP @scan1 ;Continue scanning
|
|
@done RTS
|
|
;=================================================
|
|
; Phase 2 of the Linking process
|
|
; This rtn will attempt to resolve EXTRN's by checking
|
|
; if its symbolic name is in the ENTRY table.
|
|
; If REF/EXTRN symbol cannot be resolved, the first 2 bytes
|
|
; of EXTRN record are overwritten:
|
|
; 0 EXTRN #
|
|
; 1 first char's msb is set to 1
|
|
; NB. After phase 1, some recs in EXTRN table are
|
|
; already in a singly-linked list. Their SymbolicName
|
|
; fields would have been changed to point to another
|
|
; EXTRN rec or is set to NULL if they happen to be
|
|
; the last node of the list.
|
|
; The msb of their flagbyte would be 0 (symbol is defined)
|
|
;($2552)
|
|
|
|
DoPhase2
|
|
LDA #0
|
|
LDY #EntryRecord.symbolName
|
|
STA (entRecP),Y ;Zero the len byte of ENTRY record
|
|
LDY #XtrnRecord.flags ; and flag byte of EXTRN record
|
|
STA (xtrnRecP),Y ;These recs are empty slots
|
|
LDY #$05 ;Print Resolving REF/EXTRN...
|
|
JSR DisplayMsg
|
|
JSR DisplayCR
|
|
LDY #$05
|
|
JSR StoreMsgY ;Store same msg
|
|
|
|
LDA #<xternTab
|
|
STA xtrnRecP ;Point to start
|
|
LDA #>xternTab
|
|
STA xtrnRecP+1 ; of EXTRN table
|
|
LDA #0
|
|
STA xtrnNbr ;EXTRN cnt (or EXTRN #)
|
|
|
|
; Phase2 main loop
|
|
|
|
@mainlp JSR AbortPause
|
|
LDY #XtrnRecord.flags
|
|
LDA (xtrnRecP),Y ;Get flag byte
|
|
BEQ @done ;Done w/all recs in EXTRN table
|
|
AND #%10000000 ;Is symbol undefined?
|
|
BEQ @next ;No, skip this EXTRN rec
|
|
|
|
LDY #XtrnRecord.symNamePtr
|
|
LDA (xtrnRecP),Y ;Get ptr to its symbolicname
|
|
STA symP
|
|
INY
|
|
LDA (xtrnRecP),Y
|
|
STA symP+1
|
|
JSR ScanEntryTable ;Is symbol already in ENTRY table?
|
|
BNE @noHit ;No
|
|
JSR AppendNode ;Add to singly-linked list of EXTRN recs
|
|
JMP @next ;Prepare to process next record
|
|
|
|
; The EXTRN symbol was not found in ENTRY table
|
|
|
|
@noHit LDY #XtrnRecord.flags
|
|
LDA (xtrnRecP),Y ;Get flag byte fr EXTRN record
|
|
ORA #%00000010 ;Flag as "No such label"
|
|
STA (xtrnRecP),Y
|
|
BIT WhichType ;Is object file of type REL?
|
|
BPL @notdef ;No
|
|
|
|
JSR MarkNoSymbol ;Modify SymbolicName & update EXTRN recs
|
|
JMP @next
|
|
|
|
@notdef JSR StoreUndefSym ;Report undefined symbol
|
|
|
|
@next JSR AdvNxtExtrn ;Next EXTRN record
|
|
JMP @mainlp ;Loop back
|
|
|
|
; We have finished scanning through all EXTRN recs
|
|
|
|
@done BIT WhichType ;Is OBJECT file of type REL?
|
|
BPL @exit ;No, exit this phase
|
|
|
|
; Write a tempESD file of unreferenced ENTRY & unresolved EXTRN
|
|
; records by scanning thru their respective tables
|
|
|
|
JSR MakeTmpESD ;Open tempESD file for writing
|
|
JSR WriteXtrnTmpESD ;Use info fr unresolved EXTRNs &
|
|
JSR WriteEntryTmpESD ; unreferenced ENTRYs to write file
|
|
JSR CloseTmpESD ;Mark EO ESD and close tempESD file
|
|
|
|
@exit JMP DoPhase3
|
|
;===============================
|
|
; An EXTRN Symbol cannot be found in ENTRY table
|
|
; Modify its EXTRN rec & associated Symbol rec
|
|
; Input
|
|
; xtrnRecP - Ptr to a record of EXTRN table
|
|
; xtrnNbr - EXTRN count
|
|
; Output
|
|
; symP - Ptr to a record of SymbolicName table
|
|
; (Y)=0
|
|
; The structure of SymbolicName table will be modified.
|
|
; Only 2 bytes are changed viz.
|
|
; offset 0 - len byte -> EXTRN #
|
|
; offset 1 - 1st char whose msb is off -> msb on
|
|
; ($25C6)
|
|
|
|
MarkNoSymbol
|
|
LDY #XtrnRecord.symNamePtr
|
|
LDA (xtrnRecP),Y
|
|
STA symP
|
|
INY
|
|
LDA (xtrnRecP),Y
|
|
STA symP+1
|
|
LDY #SymbolRecord.symbolName+1
|
|
LDA (symP),Y ;Is msb of its 1st char off?
|
|
BPL @1 ;Yes
|
|
DEY
|
|
LDA (symP),Y ;No, get EXTRN #
|
|
JMP @3
|
|
|
|
@1 INC xtrnNbr ;EXTRN #
|
|
BNE @2
|
|
JMP ExtrnErr ;>255 EXTRN's in REL output ESD
|
|
|
|
@2 ORA #$80 ;Set 1st char's msb to 1
|
|
STA (symP),Y
|
|
LDA xtrnNbr ;EXTRN #
|
|
@3 LDY #XtrnRecord.externNum
|
|
STA (xtrnRecP),Y
|
|
LDY #SymbolRecord.externNum
|
|
STA (symP),Y ;Overwrite its len byte w/EXTRN #
|
|
RTS
|
|
;===============================
|
|
; Check if a SymbolicName is present in
|
|
; one of the recs of ENTRY array ($4700)
|
|
; Input
|
|
; symP - ptr to a SymbolicName rec
|
|
;
|
|
; Output
|
|
; Z=1 - Yes
|
|
; Z88 - Ptr to the ENTRY record
|
|
; (Y)=0
|
|
; Uses a brute force method to search for the key
|
|
; The search is conducted record by record until
|
|
; no more records are left to be processed
|
|
; ($25F3)
|
|
|
|
ScanEntryTable
|
|
LDA #<EntryTab ;Start search fr BO ENTRY table
|
|
STA Z88
|
|
LDA #>EntryTab
|
|
STA Z88+1
|
|
|
|
@scan1 LDY #EntryRecord.symbolName
|
|
LDA (symP),Y ;Get len byte of symbolicname
|
|
CMP (Z88),Y
|
|
BNE @noHit ;Definitely no match
|
|
CMP #Str15.sizeof
|
|
BCC @doCmp
|
|
LDA #Str15.sizeof-1 ;At most 15 chars to be compared
|
|
@doCmp TAX
|
|
@cmpLup INY
|
|
LDA (symP),Y ;Compare symbolic names
|
|
CMP (Z88),Y
|
|
BNE @noHit ;No match
|
|
DEX
|
|
BNE @cmpLup ;continue
|
|
|
|
LDY #0 ;Z=1 ==> hit
|
|
RTS
|
|
|
|
@noHit LDA #EntryRecord.sizeof
|
|
LDX #Z88 ;Ptr to be adjusted
|
|
JSR AdvNextRecZ ;Adv to next ENTRY record (Z88++)
|
|
LDY #0
|
|
LDA (Z88),Y ;Get symbol's len byte fr ENTRY rec
|
|
BNE @scan1 ;Not EOT, so try again
|
|
LDY #0
|
|
LDA #1 ;Z=0 ==> Not found
|
|
RTS
|
|
;=================================================
|
|
; Check if EXTRN name is in Symbol table ($9200)
|
|
; Return a ptr to the "found" Symbol record if
|
|
; there is a match. In this case, the caller
|
|
; should not add the new Symbol record to its table.
|
|
; Input
|
|
; Output
|
|
; (symP) - ptr to the new symbolicname which is
|
|
; to be added to the Symbol Table.
|
|
; On return
|
|
; (Y)=0
|
|
; Z=1 match
|
|
; (Z88) - ptr to symbolicName record
|
|
; ($2629)
|
|
|
|
ScanSymbolTab
|
|
LDA #<symbolTab
|
|
STA Z88
|
|
LDA #>symbolTab
|
|
STA Z88+1
|
|
JMP @ckend
|
|
|
|
@mainlp LDY #SymbolRecord.symbolName
|
|
LDA (symP),Y ;Get its len byte
|
|
CMP (Z88),Y
|
|
BNE @nohit
|
|
CMP #SymbolRecord.sizeof
|
|
BCC @cmp
|
|
|
|
LDA #SymbolRecord.sizeof-1 ;Compare first 15 chars
|
|
@cmp TAX
|
|
@cmplp INY
|
|
LDA (symP),Y
|
|
CMP (Z88),Y
|
|
BNE @nohit ;No match
|
|
DEX
|
|
BNE @cmplp
|
|
|
|
LDY #0 ;Z=1
|
|
RTS
|
|
|
|
@nohit LDA #SymbolRecord.sizeof
|
|
LDX #Z88
|
|
JSR AdvNextRecZ ;Adv to next SymbolicName record
|
|
|
|
@ckend LDA Z88 ;Is EOT?
|
|
CMP symP ;NB. This rec has yet to be "added"
|
|
BNE @mainlp
|
|
LDA Z88+1 ; to the SymbolicName table
|
|
CMP symP+1
|
|
BNE @mainlp ;No, keep searching
|
|
|
|
LDY #0
|
|
LDA #1 ;Z=0
|
|
RTS
|
|
;=================================================
|
|
; Modify the ENTRY and EXTRN records by setting up
|
|
; the necessary links.
|
|
; If more than one EXTRN records refer to the ENTRY
|
|
; rec, then we setup a singly-linked list to link
|
|
; all the EXTRN recs. The field "head" will
|
|
; point to the first EXTRN rec & the field "tao;"
|
|
; point to the last EXTRN rec in the singly-linked list
|
|
;
|
|
; Input
|
|
; (xtrnRecP) - Ptr to a EXTRN record
|
|
; (Z88) - Ptr to an ENTRY record
|
|
; Output
|
|
;
|
|
; Prepare to add a new node (in the form of an EXTRN rec)
|
|
; to the singly-linked list. The pointer to a SymbolicName
|
|
; rec (symNamePtr) in the EXTRN rec is now called "next"
|
|
; (variant rec in Pascal, union in C).
|
|
; ($2668)
|
|
|
|
AppendNode
|
|
LDY #XtrnRecord.next ;XtrnRecord.symNamePtr
|
|
LDA #NULL
|
|
STA (xtrnRecP),Y ;Set "next" link to NULL
|
|
INY
|
|
STA (xtrnRecP),Y
|
|
INY ;2
|
|
LDA Z88 ;Ptr to ENTRY record whose symbolicname
|
|
STA (xtrnRecP),Y ; matches that of the current ESD entry
|
|
INY ;3
|
|
LDA Z88+1
|
|
STA (xtrnRecP),Y
|
|
|
|
LDY #XtrnRecord.flags
|
|
LDA (xtrnRecP),Y
|
|
AND #$FF-undefined ;Indicate the symbol is now defined $7F
|
|
STA (xtrnRecP),Y
|
|
AND #fwdreferenced ;Has the meaning of this bit changed?
|
|
LDY #EntryRecord.flags
|
|
EOR (Z88),Y
|
|
AND #fwdreferenced
|
|
BEQ @1 ;Yes
|
|
JSR StoreSizErr ;size mismatch (8-bit vs 16-bit)
|
|
|
|
@1 LDY #EntryRecord.flags
|
|
LDA (Z88),Y
|
|
AND #unreferenced
|
|
BEQ @2 ;=> have been referenced before
|
|
EOR (Z88),Y ;Clear the unreferenced bit
|
|
STA (Z88),Y ; but retain the other bits
|
|
|
|
; The ENTRY rec is referenced the FIRST time so set its
|
|
; "head" and "tail" fields to point to the same EXTRN rec
|
|
|
|
LDY #EntryRecord.head
|
|
LDA xtrnRecP ;Get ptr to EXTRN record
|
|
STA (Z88),Y
|
|
INY ;=21
|
|
LDA xtrnRecP+1
|
|
STA (Z88),Y
|
|
|
|
INY ;=22
|
|
LDA xtrnRecP ;Ptr to same EXTRN record
|
|
STA (Z88),Y
|
|
INY ;23
|
|
LDA xtrnRecP+1
|
|
STA (Z88),Y
|
|
RTS
|
|
|
|
; The ENTRY symbol has been referenced at least once.
|
|
; We add the new node (EXTRN record) to the end of the
|
|
; singly-linked list of EXTRN records.
|
|
|
|
@2 LDY #EntryRecord.tail
|
|
LDA (Z88),Y ;Get ptr to previous EXTRN record
|
|
STA Z82 ;Save it for later
|
|
LDA xtrnRecP
|
|
STA (Z88),Y ;Set the link to point
|
|
INY ;23
|
|
|
|
LDA (Z88),Y ; to this EXTRN record
|
|
STA Z82+1
|
|
LDA xtrnRecP+1 ; which is now the last node
|
|
STA (Z88),Y ; in the singly-linked list
|
|
|
|
LDY #XtrnRecord.next
|
|
LDA xtrnRecP ;(Z82) - previously the "tail" EXTRN record
|
|
STA (Z82),Y ;Replace its "next" link (which was NULL)
|
|
INY
|
|
LDA xtrnRecP+1 ; with ptr to this EXTRN record
|
|
STA (Z82),Y
|
|
RTS
|
|
;===============================
|
|
; Copy the temporary ESD file name to pathame buf
|
|
; ($26D1)
|
|
|
|
MovTmpESDName
|
|
LDY TempESD ;len byte
|
|
@mvLoop LDA TempESD,Y
|
|
STA pathNameBuf,Y
|
|
DEY
|
|
BPL @mvLoop
|
|
RTS
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Open a temporary (binary) ESD file for output
|
|
; This rtn will be called if there are unresolved
|
|
; EXTRN symbols
|
|
;
|
|
; Output
|
|
; (Z86) - ptr to tmpESD data buffer
|
|
; Write3RecP8+c.refNum - EXTRN # used to write tempESD file
|
|
; ($26DE)
|
|
|
|
MakeTmpESD
|
|
JSR MovTmpESDName ;Set PN to "EDASM.TempESD"
|
|
JSR PRODOS8
|
|
DC.B $C1 ;DESTROY
|
|
DC.W DestroyRecP8
|
|
|
|
LDA #0
|
|
STA CreateRecP8+C_AUXID ;auxtype
|
|
STA CreateRecP8+C_AUXID+1
|
|
LDA #BIN_type
|
|
STA CreateRecP8+C_FILEID
|
|
JSR PRODOS8
|
|
DC.B $C0 ;CREATE
|
|
DC.W CreateRecP8
|
|
BEQ @1
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@1 JSR PRODOS8
|
|
DC.B $C8 ;OPEN
|
|
DC.W Open3RecP8
|
|
BEQ @2
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@2 LDA Open3RecP8+C_OUTREF
|
|
STA Write3RecP8+C_REFNUM ;write RN for tempESD file
|
|
|
|
;===============================
|
|
SetDataBufPtr
|
|
LDA #<X9100 ;Reset to BO data buf
|
|
STA Z86 ; b4 next ESD rec is created
|
|
LDA #>X9100
|
|
STA Z86+1
|
|
RTS
|
|
;===============================
|
|
; Scan through the ENTRY table for recs whose
|
|
; SymbolicName remained unreferenced. Output info
|
|
; to tempESD file
|
|
; Input
|
|
; Output
|
|
; ($2719)
|
|
|
|
WriteEntryTmpESD
|
|
LDA #<EntryTab
|
|
STA Z8E ;Point @ BO ENTRY table
|
|
LDA #>EntryTab
|
|
STA Z8E+1 ;=> re-cycled zp loc
|
|
|
|
@scanlp JSR AbortPause
|
|
LDY #EntryRecord.flags
|
|
LDA (Z8E),Y ;Get ENTRY record's flag byte
|
|
BIT EntryRefOption ;Include ENTRY records in tempESD file?
|
|
BMI @1 ;Yes
|
|
AND #unreferenced ;Is its SymbolicName still unreferenced?
|
|
BNE @1 ;Yes
|
|
JMP @skip
|
|
|
|
@1 JSR MovSymESDBuf ;Copy symbolicname to tmpESD buf
|
|
TYA ;Save len of symbolicname
|
|
PHA
|
|
LDY #EntryRecord.flags
|
|
LDA (Z8E),Y ;Get ENTRY record's flag byte again
|
|
AND #$FF-undefined-unreferenced
|
|
STA ESDWrkRec+ESDRecord.flags ;Clear undefined/unreferenced bits
|
|
INY
|
|
LDA (Z8E),Y
|
|
STA ESDWrkRec+ESDRecord.relAddr
|
|
INY
|
|
LDA (Z8E),Y
|
|
STA ESDWrkRec+ESDRecord.relAddr+1
|
|
PLA
|
|
TAY ;Restore Y-reg
|
|
JSR AddESDBuf ;Add ENTRY data to tempESD data buf
|
|
JSR WriteESDRec ;Write out to tempESD file
|
|
|
|
@skip LDA #EntryRecord.sizeof
|
|
LDX #Z8E
|
|
JSR AdvNextRecZ ;Next ENTRY record
|
|
LDY #EntryRecord.symbolName
|
|
LDA (Z8E),Y ;Is EOT?
|
|
BNE @scanlp ;No
|
|
RTS
|
|
;===============================
|
|
; Scan through the EXTRN table for recs whose
|
|
; SymboliName remained undefined. Output info
|
|
; to tempESD file
|
|
; Input
|
|
; Output
|
|
; ($2763)
|
|
|
|
WriteXtrnTmpESD
|
|
LDA #<xternTab
|
|
STA xtrnRecP
|
|
LDA #>xternTab
|
|
STA xtrnRecP+1
|
|
|
|
@scanlp JSR AbortPause
|
|
LDY #XtrnRecord.flags
|
|
LDA (xtrnRecP),Y
|
|
BEQ @ret
|
|
AND #undefined ;$80
|
|
BEQ @next ;No
|
|
|
|
LDY #XtrnRecord.symNamePtr
|
|
LDA (xtrnRecP),Y ;Get ptr to symbolicname which
|
|
STA symP ; is stored in the Symbol Table
|
|
INY
|
|
LDA (xtrnRecP),Y
|
|
STA symP+1
|
|
LDY #SymbolRecord.symbolName+1
|
|
LDA (symP),Y ;Get its 1st char
|
|
BPL @next
|
|
AND #$7F
|
|
STA (symP),Y ; & reset its msb
|
|
|
|
LDA #SPACE
|
|
@cklup INY
|
|
CMP (symP),Y ;Look for 1st trailing blank
|
|
BEQ @Got1
|
|
CPY #Str15.sizeof-1
|
|
BCC @cklup
|
|
|
|
INY ;No trailing blanks
|
|
@Got1 DEY
|
|
TYA ;len of symbolicname
|
|
LDY #SymbolRecord.externNum
|
|
STA (symP),Y ;Overwrite the EXTRN # with len byte
|
|
JSR MakeESDRec ;Create a ESD rec (variable in size)
|
|
JSR WriteESDRec ;Write ESD data to file
|
|
@next JSR AdvNxtExtrn ;Next EXTRN record
|
|
JMP @scanlp
|
|
@ret RTS
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Input
|
|
; (Z86) - ptr to tmpESD buffer
|
|
; Output
|
|
; ($27AC)
|
|
|
|
CloseTmpESD
|
|
LDA #$00 ;Marks eo ESD
|
|
TAY
|
|
STA (Z86),Y
|
|
INC Z86
|
|
BNE @1
|
|
INC Z86+1
|
|
@1 JSR WriteESDRec ;Flush the tempESD file
|
|
LDA Write3RecP8+C_REFNUM ;Close tempESD file
|
|
JSR CloseAnyFile
|
|
RTS
|
|
;=================================================
|
|
; Write out data to tempESD binary file
|
|
; Input
|
|
; (Z86)-ptr to record in tempESD table
|
|
; Output
|
|
; ($27C1)
|
|
|
|
WriteESDRec
|
|
LDA Z86 ;Calculate # of bytes to write
|
|
SEC
|
|
SBC #<X9100
|
|
STA Write3RecP8+C_REQCNT
|
|
LDA Z86+1
|
|
SBC #>X9100
|
|
STA Write3RecP8+C_REQCNT+1
|
|
JSR PRODOS8
|
|
DC.B $CB ;WRITE
|
|
DC.W Write3RecP8
|
|
BEQ @NoErrs
|
|
JSR ErrHandler ;Don't come back
|
|
@NoErrs JMP SetDataBufPtr
|
|
;===============================
|
|
; Copy symbolicname to tmpESD data buffer
|
|
; Input
|
|
; (symP) - ptr to symbolicname record
|
|
; (Z86) - ptr to tempESD buffer ($9100)
|
|
; Output
|
|
; (Y) - len of symbolicname
|
|
; ($27DE)
|
|
|
|
MovSymESDBuf
|
|
LDY #SymbolRecord.symbolName
|
|
LDA (symP),Y ;Get len byte of symbolicname
|
|
CMP #SymbolRecord.sizeof
|
|
BCC @1
|
|
|
|
; Transfer a p-string to the temp ESD data buf
|
|
; The chars of the resulting string except the
|
|
; last one will have their msbs on.
|
|
|
|
LDA #SymbolRecord.sizeof-1
|
|
@1 TAX ;make into a counter
|
|
@cploop INY
|
|
LDA (symP),Y ;Get char
|
|
ORA #$80 ;Set msb on
|
|
DEY
|
|
STA (Z86),Y
|
|
INY
|
|
DEX
|
|
BNE @cploop
|
|
|
|
DEY
|
|
AND #$7F
|
|
STA (Z86),Y ;msb of last char is off
|
|
INY ;len of symbolicname
|
|
RTS
|
|
;===============================
|
|
; Make an ESD record for output (of unresolved EXTRNS)
|
|
; NB. An ESD record has 3/4 fields, the first one of
|
|
; which is a string of chars whose last char has its
|
|
; msb set. It is followed by 3 bytes.
|
|
; Input
|
|
; xtrnRecP - ptr to record in EXTRN table
|
|
; Z86 - ptr to record in tempESD table
|
|
; Output
|
|
; ($27FC)
|
|
|
|
MakeESDRec
|
|
JSR MovSymESDBuf
|
|
TYA ;len of symbolicname
|
|
PHA
|
|
LDY #XtrnRecord.flags
|
|
LDA (xtrnRecP),Y
|
|
AND #$FF-undefined-unreferenced-nosuchlabel
|
|
STA ESDWrkRec+ESDRecord.flags
|
|
LDY #XtrnRecord.externNum
|
|
LDA (xtrnRecP),Y
|
|
STA ESDWrkRec+ESDRecord.externNum
|
|
LDA #0
|
|
STA ESDWrkRec+ESDRecord.unused
|
|
PLA
|
|
TAY
|
|
;
|
|
; Common code for appending an ESD rec using
|
|
; info fr a rec of EXTRN/ENTRY table
|
|
; Input
|
|
; (Y) - len of symbolicname
|
|
; (Z86) - ptr to record in tempESD table
|
|
|
|
AddESDBuf
|
|
LDA ESDWrkRec+ESDRecord.flags
|
|
STA (Z86),Y
|
|
INY
|
|
LDA ESDWrkRec+ESDRecord.externNum
|
|
STA (Z86),Y
|
|
INY
|
|
LDA ESDWrkRec+ESDRecord.unused
|
|
STA (Z86),Y
|
|
INY
|
|
TYA ;size of ESD record (which is variable)
|
|
LDX #Z86
|
|
JSR AdvNextRecZ ;Adv the ptr to next ESD rec
|
|
RTS
|
|
;===============================
|
|
; Input
|
|
; Output
|
|
; Store duplicate ENTRY symbol associated messages
|
|
; ($2831)
|
|
|
|
StoreDupSym
|
|
JSR StorErr
|
|
LDY #$12 ;dup ENTRY symbol
|
|
JSR StoreMsg
|
|
JSR StoreName
|
|
LDY #$13 ;of module #
|
|
JSR StoreMsg
|
|
JSR StoreFileNum
|
|
LDY #$14 ;in module #
|
|
JSR StoreMsg
|
|
LDY #EntryRecord.fileNum
|
|
LDA (entRecP),Y ;REL file #
|
|
LDY #0 ;zero ten's digit
|
|
JSR Cnv2S ;Store 2 ASCII char in LINKMAP
|
|
JSR StoreCR
|
|
RTS
|
|
;===============================
|
|
; Input
|
|
; Output
|
|
; Store undefined EXTERN symbol associated messages
|
|
; ($2856)
|
|
|
|
StoreUndefSym
|
|
JSR StorErr
|
|
LDY #$15 ;undef EXTRN symbol
|
|
JSR StoreMsg
|
|
LDA symP ;ptr to symbolicname
|
|
STA Z88
|
|
LDA symP+1
|
|
STA Z88+1
|
|
JSR StoreName ;Store symbolic name
|
|
|
|
LDY #$14 ; in module #
|
|
JSR StoreMsg
|
|
LDY #XtrnRecord.fileNum
|
|
LDA (xtrnRecP),Y ;Get src file #
|
|
LDY #0 ;Zero ten's digit
|
|
JSR Cnv2S ;Convert to 2-byte ASCII char
|
|
JSR StoreCR
|
|
RTS
|
|
;===============================
|
|
; Input
|
|
; Output
|
|
; ($287B)
|
|
|
|
StoreSizErr
|
|
JSR StorErr
|
|
LDY #$1D ;mismatch REF-DEF size
|
|
JSR StoreMsg
|
|
JSR StoreName
|
|
LDY #$14 ; in module #
|
|
JSR StoreMsg
|
|
LDY #XtrnRecord.fileNum
|
|
LDA (xtrnRecP),Y ;Get REL file #
|
|
LDY #0 ;Zero ten's digit
|
|
JSR Cnv2S ;Convert
|
|
JSR StoreCR
|
|
RTS
|
|
;===============================
|
|
; Store "ERR:" to LINKMAP file
|
|
; Input
|
|
; Output
|
|
|
|
StorErr
|
|
LDA #'E'
|
|
JSR StoreChar
|
|
LDA #'R'
|
|
JSR StoreChar
|
|
JSR StoreChar
|
|
LDA #':'
|
|
JMP StoreChar
|
|
;===============================
|
|
; Store to LINKMAP file
|
|
; Input
|
|
; (Y) = message #
|
|
; Output
|
|
|
|
StoreMsgY
|
|
BIT MapOption ;Store into LINKMAP file ?
|
|
BPL doRTS ;No, ret
|
|
JSR StoreMsg
|
|
JMP StoreCR
|
|
;===============================
|
|
; Output a Message to LINKMAP file
|
|
; Input
|
|
; Output
|
|
; (Y)-index into message sub-tables
|
|
; You may think of (Y) as being the err #
|
|
; ($28B4)
|
|
|
|
StoreMsg
|
|
LDA MsgTabLo,Y
|
|
STA msgP
|
|
LDA MsgTabHi,Y
|
|
STA msgP+1
|
|
LDY #0
|
|
@loop LDA (msgP),Y
|
|
CMP #'\' ;end of msg
|
|
BEQ doRTS
|
|
JSR StoreChar
|
|
INY
|
|
JMP @loop ;next char
|
|
doRTS RTS
|
|
;=================================================
|
|
; Phase 3 of the Linking process
|
|
; Relocate the object code. The RLD of each SRC file
|
|
; is used to relocate the code from each file. Code
|
|
; fr SRC files whose names are preceded by a * in
|
|
; the cmd file are not included in the OBJECT file.
|
|
; Mem reserved for the Symbol table ($9200-$92FF) is
|
|
; re-used as a data buffer. 256 bytes of the code image
|
|
; of a SRC file are read into this area first b4
|
|
; being move forward into previous mem page ($9100)
|
|
; for patching.
|
|
;
|
|
;
|
|
; Input
|
|
; Output
|
|
; ModuleNbr - # of SRC file
|
|
; CurrORG - Starting PC for curr SRC file
|
|
; (objCodeLen)
|
|
; (LowerBound)
|
|
; (UpperBound,9C)
|
|
; ($28CE)
|
|
|
|
DoPhase3
|
|
LDY #$06 ;Report "Relocating objcode..."
|
|
JSR DisplayMsg
|
|
JSR DisplayCR
|
|
LDY #$06
|
|
JSR StoreMsgY ;save a copy in LINKMAP
|
|
|
|
LDA #0
|
|
STA ModuleNbr
|
|
STA objCodeLen ;EO REL-type OBJECT file
|
|
STA objCodeLen+1
|
|
|
|
LDA Origin
|
|
STA CurrORG ;Starting PC
|
|
LDA Origin+1
|
|
STA CurrORG+1
|
|
JSR MoveObjName ;Set PN to "EDASM.LINKOBJ"
|
|
JSR PRODOS8
|
|
DC.B $C1 ;DESTROY
|
|
DC.W DestroyRecP8
|
|
|
|
LDA Origin
|
|
STA CreateRecP8+C_AUXID
|
|
LDA Origin+1
|
|
STA CreateRecP8+C_AUXID+1 ;auxtype
|
|
LDA TargetObjType ;filetype of OBJECT file
|
|
STA CreateRecP8+C_FILEID
|
|
JSR PRODOS8
|
|
DC.B $C0 ;CREATE
|
|
DC.W CreateRecP8
|
|
BNE @1
|
|
|
|
JSR PRODOS8 ;OPEN the OBJECT file
|
|
DC.B $C8
|
|
DC.W Open3RecP8
|
|
BEQ @2
|
|
|
|
@1 JSR ErrHandler ;Don't come back
|
|
|
|
@2 LDA Open3RecP8+C_OUTREF ;OBJECT file
|
|
STA Write3RecP8+C_REFNUM ;RN to write OBJECT file
|
|
BIT WhichType ;What is the OBJECT file type?
|
|
BPL @4 ;=>BIN/SYS
|
|
|
|
; Write the header of OBJ file which is a 2-byte value
|
|
; denoting the length of its code image.
|
|
|
|
LDA #$00 ;REL OBJECT file
|
|
STA X9100
|
|
STA X9100+1
|
|
STA Write3RecP8+C_REQCNT+1 ;Write 2 zeroes for
|
|
LDA #$02 ; the code image len
|
|
STA Write3RecP8+C_REQCNT
|
|
JSR PRODOS8
|
|
DC.B $CB ;WRITE
|
|
DC.W Write3RecP8
|
|
BEQ @3
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@3 LDA WriteMapRecP8+C_REFNUM
|
|
JSR CloseAnyFile
|
|
JSR OpenTmpRLD ;Open a new tempRLD file 4 writing
|
|
|
|
@4 JSR ResetFilePos ;Set file posn to BO cmd file
|
|
|
|
; Skip all directives at the start cmd file
|
|
; to get at the SRC pathnames
|
|
|
|
@skip JSR ReadOneCmd ;Do we have a SRC filename?
|
|
BNE Phs3Loop ;If not cr/space => pathname
|
|
CMP #CR
|
|
BNE @skip ;A leading space, skip to the directive
|
|
JMP WrongOrder ;Invalid cmd order
|
|
|
|
; Mainloop for phase 3
|
|
; Buffers used for :
|
|
; reading RLD = $0C00-$1FFF
|
|
; Patching code = $9100-$91FF
|
|
; reading code = $9200-$92FF
|
|
|
|
Phs3Loop
|
|
JSR ShowLineBuf ;Show PN of the SRC file being processed
|
|
JSR OpenSrcFile ;Open it for reading
|
|
BIT Z9E ;Is src PN preceded by *?
|
|
BPL @1 ;No
|
|
|
|
LDA OpenSrcRecP8+C_OUTREF ;Close it
|
|
JSR CloseAnyFile
|
|
JMP NxtModule ;Skip reading from it
|
|
|
|
@1 LDA #2
|
|
CLC
|
|
ADC srcCodeLen ;Set file posn to start of
|
|
STA MarkSrcRecP8+C_MARK
|
|
LDA #0
|
|
ADC srcCodeLen+1
|
|
STA MarkSrcRecP8+C_MARK+1 ; Relocation Dictionary
|
|
|
|
LDA OpenSrcRecP8+C_OUTREF
|
|
STA MarkSrcRecP8+C_REFNUM
|
|
STA ReadCodeRecP8+C_REFNUM
|
|
JSR PRODOS8
|
|
DC.B $CE ;SET_MARK
|
|
DC.W MarkSrcRecP8
|
|
BEQ Phs31
|
|
Jmp2EH JSR ErrHandler ;Don't come back
|
|
|
|
Phs31 JSR ReadMax ;Have we read entire RLD?
|
|
BCC @1 ;Yes
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@1 LDA #2 ;Set file posn to BO
|
|
STA MarkSrcRecP8+C_MARK ; code image of SRC file
|
|
LDA #0
|
|
STA MarkSrcRecP8+C_MARK+1
|
|
JSR PRODOS8
|
|
DC.B $CE ;SET_MARK
|
|
DC.W MarkSrcRecP8
|
|
BNE Jmp2EH
|
|
|
|
LDA #0
|
|
STA LowerBound
|
|
STA LowerBound+1
|
|
STA UpperBound
|
|
STA UpperBound+2
|
|
JSR Read1PageCode ;Read the first $100 bytes of code image
|
|
|
|
; Loop to process all recs in the RLD of curr SRC file
|
|
|
|
Phs3Loop1
|
|
JSR AbortPause
|
|
LDY #RLDRecord.flags
|
|
LDA (srcP),Y ;Get flag byte fr RLD record
|
|
STA RLD_Flags
|
|
BNE @1
|
|
JMP FlushLoop ;EO RLD => done w/this SRC file
|
|
|
|
; The code below doesn't check for overflow
|
|
; What happens if field offset is a # > $6EFF?
|
|
|
|
@1 LDY #RLDRecord.codeOffset
|
|
LDA (srcP),Y
|
|
STA Z80 ;Field offset in code image
|
|
CLC
|
|
ADC #<X9100
|
|
STA Z86 ;location to patch???
|
|
INY
|
|
LDA (srcP),Y
|
|
STA Z80+1
|
|
ADC #>X9100
|
|
STA Z86+1 ;$9100-$FFFF?
|
|
|
|
; Check if the field offset is within the "window"
|
|
; bounds LowerBound and UpperBound. Since no effort is made
|
|
; to check the lower bound, it is assumed that the
|
|
; field offset is past this when (Z80) < UpperBound
|
|
; It is also assumed that all records (in the RLD) have been
|
|
; arranged with field offsets in ascending order
|
|
|
|
@chkLoop
|
|
LDA Z80 ;Is field offset < upper bounds?
|
|
CMP UpperBound
|
|
LDA Z80+1
|
|
SBC UpperBound+2
|
|
BCC @2 ;Yes, within the "window"
|
|
JSR FlushCode ;No, read another page of code
|
|
JMP @chkLoop ; and check again
|
|
|
|
; The ptr Z86 could be calculated using the formula
|
|
; (Z86)=(Z80) - (LowerBound) + $9100
|
|
|
|
@2 SEC
|
|
LDA Z86
|
|
SBC LowerBound
|
|
STA Z86 ;Z86 -= LowerBound
|
|
LDA Z86+1 ;If there is no overflow above,
|
|
SBC LowerBound+1
|
|
STA Z86+1 ; then $9100 =< (Z86) =< $91FF
|
|
|
|
BIT WhichType ;an REL object file?
|
|
BPL @3 ;No => BIN/SYS
|
|
|
|
LDY #RLDRecord.codeOffset+1
|
|
LDA Z80 ;Field offset
|
|
CLC
|
|
ADC objCodeLen ;Len of Code Image of
|
|
PHA
|
|
LDA Z80+1 ; REL OBJECT file excluding
|
|
ADC objCodeLen+1 ; that of curr SRC file
|
|
STA (srcP),Y ;Patch field offset of RLD record
|
|
DEY ;Y=1
|
|
|
|
PLA
|
|
STA (srcP),Y
|
|
|
|
@3 BIT RLD_Flags ;Is size of relocatable field 2?
|
|
BMI @6 ;Yes
|
|
|
|
LDY #0 ;Get original addr (lo/hi)
|
|
LDA (Z86),Y ; byte fr the code image
|
|
BIT RLD_Flags ;Is it hi-8 of addr?
|
|
BVS @4 ;Yes
|
|
|
|
; (A) has the lo-8 of the addr (fr a > byte operator)
|
|
; Since only the lobyte is used to patch the code
|
|
; any value for the hibyte can be used. So let's
|
|
; use 0 as RelAdrHi
|
|
|
|
STA RelAdr
|
|
LDA #$00
|
|
STA RelAdr+1
|
|
JSR GetRelAdr ;Calc/get relocated addr
|
|
LDY #0
|
|
LDA RelAdr ;Use the lo 8-bit to
|
|
STA (Z86),Y ; patch the code image
|
|
JMP @next ;Skip code below
|
|
|
|
; (A) has the hi-8 of the addr (fr a < byte operator)
|
|
; For this case, we need both the low & high bytes
|
|
; of the original addr if relocation rec is not
|
|
; flagged as EXTRN symbol-type
|
|
|
|
@4 STA RelAdr+1 ;hi-byte
|
|
LDY #RLDRecord.low8bits
|
|
LDA (srcP),Y ;lo 8-bits/EXTRN symbol #
|
|
STA RelAdr
|
|
LDA RLD_Flags ;Get RLD flag byte
|
|
AND #$10 ;Is field EXTRN 16-bit reference?
|
|
BEQ @5 ;No
|
|
|
|
LDA #$00
|
|
STA RelAdr ;Overwrite EXTRN symbol #
|
|
|
|
; On fall thru, the relocated addr will not be
|
|
; calculated but obtained from an ENTRY rec if
|
|
; it is available.
|
|
|
|
@5 JSR GetRelAdr ;Calc/get the relocated addr
|
|
LDY #0
|
|
LDA RelAdr+1
|
|
STA (Z86),Y ;Patch code image
|
|
JMP @next ;Skip code below
|
|
|
|
; Size of relocatable field is 2
|
|
; Get relocated addr fr the RLD rec
|
|
|
|
@6 LDY #0
|
|
LDA RLD_Flags ;Get RLD rec's flag byte
|
|
AND #$20 ;Normal/Reversed order?
|
|
BNE @7
|
|
LDA (Z86),Y ;Little Endian (reversed order)
|
|
STA RelAdr
|
|
INY
|
|
LDA (Z86),Y
|
|
STA RelAdr+1
|
|
JSR GetRelAdr ;Calc/get relocated addr
|
|
|
|
LDY #0
|
|
LDA RelAdr
|
|
STA (Z86),Y ;Patch the code
|
|
INY
|
|
LDA RelAdr+1
|
|
STA (Z86),Y
|
|
JMP @next ;=>next RLD
|
|
|
|
; Handle a Big Endian
|
|
|
|
@7 LDA (Z86),Y
|
|
STA RelAdr+1 ;hiaddr
|
|
INY
|
|
LDA (Z86),Y
|
|
STA RelAdr ;loaddr
|
|
JSR GetRelAdr ;Calc/get relocated addr
|
|
LDY #0
|
|
LDA RelAdr+1
|
|
STA (Z86),Y ;Patch the code
|
|
INY
|
|
LDA RelAdr
|
|
STA (Z86),Y
|
|
|
|
@next LDA #RLDRecord.sizeof
|
|
LDX #srcP
|
|
JSR AdvNextRecZ ;Adv srcP to next RLD rec
|
|
JMP Phs3Loop1 ; & loop back to process it
|
|
;===============================
|
|
;
|
|
; Flush object code if neccessary. Move buffered code
|
|
; forward into "window" ($9100-$91FF) so that another
|
|
; page of code image can be read into the $9200 data
|
|
; buffer. The variables LowerBound & UpperBound are
|
|
; edges of this "window".
|
|
; Normally (UpperBound - LowerBound) = $100 except when
|
|
; the last (partial) page of code is read. In this
|
|
; case (UpperBound - LowerBound) < $100
|
|
; Input
|
|
; LowerBound -
|
|
; UpperBound -
|
|
; Output
|
|
; UpperBound -
|
|
;
|
|
|
|
FlushCode
|
|
LDA UpperBound ;Do we need to flush OBJECT code b4
|
|
ORA UpperBound+2 ; b4 we "move" our window forward?
|
|
BEQ @1 ;No, we are still @ BO of SRC file
|
|
JSR WritePatchedCode ;Yes
|
|
|
|
@1 LDY #0 ;Move buffered Code Image
|
|
@mvlup LDA X9200,Y ; forward into our "window"
|
|
STA X9100,Y ; @ $9100-$91FF so we can
|
|
INY
|
|
BNE @mvlup
|
|
JSR Read1PageCode ; load another page into $9200 buf
|
|
|
|
LDA UpperBound
|
|
STA LowerBound
|
|
LDA UpperBound+2
|
|
STA LowerBound+1
|
|
INC UpperBound+2 ; Incr by 1 page
|
|
|
|
LDA UpperBound
|
|
CMP srcCodeLen ;Has the entire code image
|
|
LDA UpperBound+2
|
|
CMP srcCodeLen+1 ; of this SRC file been read?
|
|
BCC doRTS1 ;No
|
|
|
|
LDA srcCodeLen
|
|
STA UpperBound ;This is the upper limit of
|
|
LDA srcCodeLen+1 ; the "window" of code
|
|
STA UpperBound+2
|
|
doRTS1 RTS
|
|
;===============================
|
|
; Write out object code @ $9100
|
|
; Input
|
|
; LowerBound -
|
|
; UpperBound -
|
|
; Output
|
|
|
|
WritePatchedCode
|
|
SEC
|
|
LDA UpperBound
|
|
SBC LowerBound
|
|
STA Write3RecP8+C_REQCNT ;# of bytes to write
|
|
LDA UpperBound+2
|
|
SBC LowerBound+1
|
|
STA Write3RecP8+C_REQCNT+1 ; usually $100 bytes
|
|
JSR PRODOS8
|
|
DC.B $CB ;WRITE
|
|
DC.W Write3RecP8
|
|
BEQ doRTS1
|
|
|
|
JM2EH JSR ErrHandler ;Don't come back
|
|
|
|
;================================================
|
|
; Read $100 bytes of data into buffer starting @ $9200
|
|
; fr SRC file. The symbol table @ $9200 is re-used
|
|
; as a read data buffer.
|
|
; Output
|
|
; Z=1
|
|
; (A) = $4C if EOF or
|
|
; = $00 read succeeded
|
|
|
|
Read1PageCode
|
|
LDA #0
|
|
STA ReadCodeRecP8+C_REQCNT
|
|
LDA #1
|
|
STA ReadCodeRecP8+C_REQCNT+1
|
|
LDA #<X9200 ;Use this as our R/W Data Buf
|
|
STA ReadCodeRecP8+C_DATABUF
|
|
LDA #>X9200
|
|
STA ReadCodeRecP8+C_DATABUF+1
|
|
JSR PRODOS8
|
|
DC.B $CA ;READ
|
|
DC.W ReadCodeRecP8
|
|
BEQ doRTS1 ;If no errs, just return
|
|
|
|
CMP #$4C ;EOF?
|
|
BNE JM2EH ;No -> err handler
|
|
RTS ;We have read the entire SRC file
|
|
|
|
; We have finish patching this file so read the rest
|
|
; of the SRC file and write it out to OBJ file.
|
|
|
|
FlushLoop
|
|
LDA UpperBound
|
|
CMP srcCodeLen
|
|
BNE @1
|
|
LDA UpperBound+2
|
|
CMP srcCodeLen+1
|
|
BEQ @done ;Done w/this SRC file
|
|
@1 JSR FlushCode ;Keep flushing objcode N reading
|
|
JMP FlushLoop ; code image until we are done
|
|
|
|
@done JSR WritePatchedCode ;Append rest of OBJECT code
|
|
LDA ReadCodeRecP8+C_REFNUM
|
|
JSR CloseAnyFile
|
|
JSR AppendTmpRLD ;Append patched RLD @ srcDataBuf
|
|
|
|
LDX ModuleNbr
|
|
LDA CurrORG ;Starting posn counter
|
|
STA orgAdrLo,X ; for this SRC file
|
|
LDA CurrORG+1
|
|
STA orgAdrHi,X
|
|
JSR CalcFilePos ;adj PC?
|
|
|
|
LDA CurrORG+1
|
|
STA EndAddrHi,X
|
|
LDA CurrORG
|
|
STA EndAddrLo,X
|
|
BNE @2
|
|
DEC EndAddrHi,X ;End posn counter
|
|
@2 DEC EndAddrLo,X ; for this SRC file
|
|
|
|
NxtModule
|
|
INC ModuleNbr ;Next SRC module
|
|
DoNxtCmd
|
|
JSR ReadOneCmd ;Is it a pathname?
|
|
BNE ToLoopBack ;Yes, prepare to loop back
|
|
CMP #CR
|
|
BEQ DonePhs3 ;Empty line => Finish all cmds
|
|
JSR IsAlign ;Is it Align directive?
|
|
BCC @1 ;Proceed to check further
|
|
JMP DoBreak ;Don't comeback
|
|
|
|
@1 BEQ @ckAln ;Yes, it's an ALN option
|
|
JMP WrongOrder ;cmd order err
|
|
|
|
@ckAln LDA CurrORG ;Already aligned @ start of mempage?
|
|
BEQ DoNxtCmd ;Yes, read another cmd line
|
|
|
|
LDX #0
|
|
TXA
|
|
@zloop STA X9100,X ;zero this
|
|
INX
|
|
BNE @zloop
|
|
|
|
LDA #0
|
|
SEC
|
|
SBC CurrORG
|
|
STA Write3RecP8+C_REQCNT ;# of zero bytes to fill
|
|
STA srcCodeLen ; Re-used
|
|
LDA #0
|
|
STA Write3RecP8+C_REQCNT+1
|
|
STA srcCodeLen+1 ;Used by code at $2BA2
|
|
JSR PRODOS8
|
|
DC.B $CB ;WRITE
|
|
DC.W Write3RecP8
|
|
BNE JM2EH2
|
|
|
|
JSR CalcFilePos ;Adj PC
|
|
JMP DoNxtCmd ;Read next cmd line
|
|
|
|
ToLoopBack
|
|
JMP Phs3Loop ;Loop back to process next SRC file
|
|
|
|
JM2EH2 JSR ErrHandler ;Don't come back
|
|
;===============================
|
|
; Adjust file posn
|
|
; Input
|
|
; Output
|
|
; (objCodeLen) - curr val of code image len
|
|
; ($2BA2)
|
|
|
|
CalcFilePos
|
|
LDA srcCodeLen
|
|
CLC
|
|
ADC CurrORG
|
|
STA CurrORG ;CurrORG += srcCodeLen
|
|
LDA srcCodeLen+1
|
|
ADC CurrORG+1
|
|
STA CurrORG+1
|
|
BIT WhichType ;is object file of type REL ?
|
|
BPL @ret ;No -> exit
|
|
|
|
CLC
|
|
LDA srcCodeLen
|
|
ADC objCodeLen
|
|
STA objCodeLen ;objCodeLen += srcCodeLen
|
|
LDA srcCodeLen+1
|
|
ADC objCodeLen+1
|
|
STA objCodeLen+1
|
|
@ret RTS
|
|
|
|
; Prepare to exit Phase 3
|
|
|
|
DonePhs3
|
|
BIT WhichType ;an REL object file?
|
|
BPL @isREL ;No
|
|
|
|
; Write RLD marker ($00) to the OBJ file
|
|
|
|
LDY #0
|
|
STY srcDataBuf
|
|
STY WriteTmpRecP8+C_REQCNT+1
|
|
INY
|
|
STY WriteTmpRecP8+C_REQCNT ;# of bytes to write=1
|
|
JSR WrtTempRld ;Marks EO RLD file
|
|
|
|
@isREL BIT WhichType ;Is it a REL object file?
|
|
BMI DoPhase4 ;Yes
|
|
JMP ClsObjFile
|
|
;=================================================
|
|
; Phase 4 of the Linking process done only if
|
|
; the OBJECT file is of type REL
|
|
; Contents of TempRLD and TempESD files are appended
|
|
; to the relocatable OBJECT file
|
|
; Input
|
|
; Output
|
|
; ($2BDF)
|
|
|
|
DoPhase4
|
|
LDY #$07
|
|
JSR DisplayMsg
|
|
JSR DisplayCR
|
|
LDA WriteTmpRecP8+C_REFNUM ;RN of tempRLD file
|
|
STA SMarkBOFRecP8+C_REFNUM
|
|
JSR PRODOS8
|
|
DC.B $CE ;SET_MARK
|
|
DC.W SMarkBOFRecP8 ;Set file posn to BO tempRLD file
|
|
BEQ @1
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@1 JSR AppendTmpRLDESD ;Append tempRLD to OBJ file
|
|
LDA WriteTmpRecP8+C_REFNUM
|
|
JSR CloseAnyFile ;Now close tempRLD file
|
|
JSR AbortPause
|
|
JSR MovTmpESDName ;Set PN to TempESD
|
|
JSR PRODOS8
|
|
DC.B $C8 ;OPEN
|
|
DC.W Open2RecP8
|
|
BEQ @2
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@2 LDA Open2RecP8+C_OUTREF
|
|
STA WriteTmpRecP8+C_REFNUM
|
|
JSR AppendTmpRLDESD ;Append TempESD to REL OBJECT file
|
|
LDA WriteTmpRecP8+C_REFNUM
|
|
JSR CloseAnyFile ;Now close tempESD
|
|
|
|
LDA Open3RecP8+C_OUTREF
|
|
STA SMarkBOFRecP8+C_REFNUM ;Posn to BO REL OBJECT file
|
|
JSR PRODOS8
|
|
DC.B $CE ;SET_MARK
|
|
DC.W SMarkBOFRecP8
|
|
BEQ @3
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@3 LDA objCodeLen ;Write the CodeImage Len
|
|
STA X9100
|
|
LDA objCodeLen+1 ; of REL OBJECT file
|
|
STA X9100+1
|
|
LDA #0
|
|
STA Write3RecP8+C_REQCNT+1
|
|
LDA #2 ; which is 2 bytes
|
|
STA Write3RecP8+C_REQCNT
|
|
JSR PRODOS8
|
|
DC.B $CB ;WRITE
|
|
DC.W Write3RecP8
|
|
BEQ @4
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@4 JSR AbortPause
|
|
JSR OpenMapAppend ;Open LINKMAP file in append mode
|
|
JMP ClsObjFile
|
|
;===============================
|
|
;
|
|
; Read entire contents of tempRLD/tempESD and append
|
|
; it to the OBJECT file (which is of type REL)
|
|
;
|
|
; Input
|
|
; Output
|
|
; ($2C5A)
|
|
|
|
AppendTmpRLDESD
|
|
LDA WriteTmpRecP8+C_REFNUM ;RN of tempRLD/tempESD file
|
|
STA RWFileRecP8+C_REFNUM
|
|
JSR ReadChunk ;Read data chunk fr input file
|
|
PHP ;Save for later
|
|
BCC @1
|
|
CMP #$10
|
|
BEQ @1 ;Not EOF
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@1 LDA Open3RecP8+C_OUTREF ;OBJECT file's RN
|
|
STA RWFileRecP8+C_REFNUM ;Write same data chunk
|
|
LDA RWFileRecP8+C_TRANSCNT
|
|
STA RWFileRecP8+C_REQCNT
|
|
LDA RWFileRecP8+C_TRANSCNT+1
|
|
STA RWFileRecP8+C_REQCNT+1 ; to the OBJECT file
|
|
JSR PRODOS8
|
|
DC.B $CB ;WRITE
|
|
DC.W RWFileRecP8
|
|
BEQ @2
|
|
JSR ErrHandler ;Don't come back
|
|
@2 PLP ;Has last chunk been read?
|
|
BCS AppendTmpRLDESD ;No, do another chunk
|
|
RTS
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
ClsObjFile
|
|
LDA Open3RecP8+C_OUTREF ;Finally, close OBJECT file
|
|
JSR CloseAnyFile
|
|
BIT WhichType ;Was it relocatable OBJECT file?
|
|
BPL @skipMsg ;No
|
|
|
|
LDY #$07 ;Report "Phase 4 : Generating..."
|
|
JSR StoreMsgY
|
|
@skipMsg
|
|
BIT MapOption ;Output to LINKMAP?
|
|
BMI @sort ;Yes
|
|
JMP Phs5Done
|
|
|
|
@sort BIT SortOption ;Sort LoadMap table?
|
|
BMI DoPhase5 ;Yes
|
|
JMP Phs5Done
|
|
;=================================================
|
|
; Phase 5 of the Linking process
|
|
; Sort Relocated Adr table
|
|
; First create a LoadMap table of 4-byte records
|
|
; The LoadMap table starts @ $9100
|
|
; Layout of each record is:
|
|
; DW ptr to an ENTRY table rec
|
|
; DW relocated addr stored in the ENTRY table rec
|
|
;
|
|
; Output:
|
|
; (entRecP) - ptr to a rec in ENTRY table
|
|
; (Z86) - ptr to a rec in LoadMap table
|
|
; (Z80) - ptr to EO LoadMap table
|
|
; ($2CAB)
|
|
|
|
DoPhase5
|
|
LDY #$08
|
|
JSR DisplayMsg
|
|
JSR DisplayCR
|
|
LDY #$08
|
|
JSR StoreMsgY
|
|
|
|
LDA #<EntryTab ;NB. The ENTRY table is still in mem
|
|
STA entRecP ;Set up a ptr to its beginning
|
|
LDA #>EntryTab
|
|
STA entRecP+1
|
|
LDA #<X9100 ;4-byte records in LoadMap table
|
|
STA Z86
|
|
LDA #>X9100
|
|
STA Z86+1
|
|
LDA #0 ;Total # of records in
|
|
STA NumRecs ; ENTRY table to be sorted
|
|
STA NumRecs+1
|
|
|
|
; The code below builds the unsorted LoadMap table
|
|
|
|
@build JSR AbortPause
|
|
LDY #EntryRecord.symbolName
|
|
LDA (entRecP),Y ;EO ENTRY table?
|
|
BEQ @nomore ;Yes
|
|
|
|
LDA entRecP
|
|
STA (Z86),Y ;Points to record in ENTRY table
|
|
INY
|
|
LDA entRecP+1
|
|
STA (Z86),Y
|
|
|
|
LDY #EntryRecord.relAddr
|
|
LDA (entRecP),Y ;Get relocated addr associated with
|
|
PHA
|
|
INY
|
|
LDA (entRecP),Y ; the SymbolicName of the ENTRY rec
|
|
LDY #LoadMapRecord.sizeof-1
|
|
STA (Z86),Y ; and store in LoadMap record
|
|
PLA
|
|
DEY
|
|
STA (Z86),Y
|
|
|
|
LDA #LoadMapRecord.sizeof
|
|
LDX #Z86
|
|
JSR AdvNextRecZ ;Adv to next LoadMap rec
|
|
JSR AdvNxtEntry ;Adv to next ENTRY record
|
|
INC NumRecs ;rec count
|
|
BNE @1
|
|
INC NumRecs+1
|
|
@1 JMP @build ;Continue to build LoadMap table
|
|
|
|
; Initial LoadMap table has been build
|
|
|
|
@nomore LDY #LoadMapRecord.entryPtr
|
|
TYA ;(A)=0
|
|
STA (Z86),Y ;Mark EO LoadMap table
|
|
INY
|
|
STA (Z86),Y ; with a NULL
|
|
|
|
LDA Z86
|
|
STA Z80 ;(Z80)=EO LoadMap table
|
|
LDA Z86+1
|
|
STA Z80+1
|
|
JSR SortLoadMap ;Sort it
|
|
JMP Phs5Done
|
|
;===============================
|
|
; Sort the Load (addr) Map
|
|
; Shell-Metzner Sort
|
|
; Input
|
|
; Output
|
|
; ($2D19)
|
|
|
|
SortLoadMap
|
|
LDA NumRecs ;Jump := # of elements N
|
|
STA Jump
|
|
LDA NumRecs+1
|
|
STA Jump+1
|
|
|
|
; While Jump <> 0
|
|
|
|
WhileLoop
|
|
LSR Jump+1 ;Jump := Jump div 2
|
|
ROR Jump
|
|
LDA Jump
|
|
ORA Jump+1
|
|
BNE @1 ;Not done yet
|
|
RTS
|
|
|
|
@1 SEC
|
|
LDA NumRecs
|
|
SBC Jump
|
|
STA EndIndex
|
|
LDA NumRecs+1
|
|
SBC Jump+1
|
|
STA EndIndex+1
|
|
|
|
LDX #0
|
|
STX StartIndex+1
|
|
INX
|
|
STX StartIndex
|
|
ForLoop JSR AbortPause
|
|
|
|
; FOR JJJ := 1 to NumRecs-Jump
|
|
|
|
LDA StartIndex
|
|
STA JJJ
|
|
LDA StartIndex+1
|
|
STA JJJ+1
|
|
|
|
; REPEAT
|
|
|
|
RepeatLoop
|
|
CLC
|
|
LDA JJJ
|
|
ADC Jump
|
|
STA III ;I := J+Jump
|
|
LDA JJJ+1
|
|
ADC Jump+1
|
|
STA III+1
|
|
|
|
LDX #3
|
|
@cploop LDA JJJ,X
|
|
STA J_TH,X
|
|
DEX
|
|
BPL @cploop
|
|
|
|
; Mulby4 and add to X9100-4 ($90FC)
|
|
; Calculate indices to the elements to be compared
|
|
; (J_TH) - Ptr to j-th element
|
|
; (I_TH) - Ptr to i-th element
|
|
|
|
LDX #2
|
|
@mulLoop
|
|
ASL J_TH,X ;x4
|
|
ROL J_TH+1,X
|
|
ASL J_TH,X
|
|
ROL J_TH+1,X
|
|
|
|
CLC
|
|
LDA #<X9100-4
|
|
ADC J_TH,X
|
|
STA J_TH,X
|
|
LDA #>X9100-4
|
|
ADC J_TH+1,X
|
|
STA J_TH+1,X
|
|
DEX
|
|
DEX
|
|
BEQ @mulLoop
|
|
|
|
BIT IsNumSort ;alphabetic sort?
|
|
BPL AlfaSort ;Yes
|
|
|
|
; Sort load addresses numerically in ascending order
|
|
|
|
LDY #3
|
|
LDA (J_TH),Y ;Get load addr (Hibyte)
|
|
CMP (I_TH),Y
|
|
BEQ @eq
|
|
BCS @gt ;Greater than
|
|
@lt JMP NEXTJ ;Less than
|
|
@eq DEY
|
|
LDA (I_TH),Y ;Get load addr (lobyte)
|
|
CMP (J_TH),Y
|
|
BCS @lt ;Less than
|
|
@gt LDY #3
|
|
BNE SwapLoop ;Always -> Swap the records
|
|
|
|
; Sort SymbolicName alphabetically
|
|
; IF ENTRY[J].name > ENTRY[I].name then SWAP(Ary[J], Ary[I])
|
|
; The 1st field of an ENTRY rec is a 16-byte p-string
|
|
|
|
AlfaSort
|
|
LDY #0
|
|
LDA (J_TH),Y ;Get ptr to j-th
|
|
TAX ; ENTRY rec
|
|
INY
|
|
LDA (J_TH),Y
|
|
STA ENTRPJ+1
|
|
STX ENTRPJ
|
|
LDA (I_TH),Y
|
|
TAX
|
|
DEY ;=0
|
|
|
|
LDA (I_TH),Y ;Get ptr to i-th
|
|
STA ENTRPI ; ENTRY rec
|
|
STX ENTRPI+1
|
|
LDA (ENTRPJ),Y ;Get len byte of symbolic name
|
|
CMP (ENTRPI),Y
|
|
BEQ @LtOrEq
|
|
BCC @LtOrEq
|
|
|
|
LDA (ENTRPI),Y ;The len of this symbolic name is shorter
|
|
@LtOrEq TAX ;# of chars to compare
|
|
INY ;=1
|
|
|
|
@CmpLup LDA (ENTRPJ),Y ;Get char fr symbolic name
|
|
CMP (ENTRPI),Y
|
|
BNE @NoHit ;No match
|
|
INY
|
|
CPY #Str15.sizeof ;At most 15 chars will be compared
|
|
BCS NEXTJ ;All chars matched
|
|
DEX
|
|
BNE @CmpLup
|
|
|
|
LDA #SPACE
|
|
CMP (ENTRPJ),Y
|
|
BEQ NEXTJ
|
|
SEC ;flag we have to do a swap
|
|
@NoHit BCC NEXTJ ;C=0 -> 1st symbolic name < 2nd
|
|
|
|
; Swap the records in LoadMap
|
|
; Too costly to swap those in ENTRY table
|
|
|
|
LDY #3
|
|
SwapLoop
|
|
LDA (J_TH),Y ;Swap the ptrs as
|
|
TAX
|
|
LDA (I_TH),Y
|
|
STA (J_TH),Y ; well as the corr load addrs
|
|
TXA
|
|
STA (I_TH),Y
|
|
DEY
|
|
BPL SwapLoop
|
|
|
|
SEC
|
|
LDA JJJ ;J > Jump
|
|
SBC Jump
|
|
STA JJJ
|
|
LDA JJJ+1
|
|
SBC Jump+1 ;J := J - Jump
|
|
STA JJJ+1 ;Is J > Jump?
|
|
BMI NEXTJ ;No, less than
|
|
ORA JJJ
|
|
BEQ NEXTJ ;No, J := Jump
|
|
JMP RepeatLoop
|
|
|
|
; UNTIL JJJ =< Jump
|
|
|
|
NEXTJ INC StartIndex
|
|
BNE @1
|
|
INC StartIndex+1
|
|
|
|
@1 LDA StartIndex+1 ;Finish w/FOR loop?
|
|
CMP EndIndex+1
|
|
BCC @next
|
|
BEQ @3
|
|
@2 JMP WhileLoop ;No
|
|
@3 LDA EndIndex
|
|
CMP StartIndex
|
|
BCC @2
|
|
@next JMP ForLoop
|
|
;-----
|
|
|
|
Phs5Done
|
|
BIT MapOption ;Write LINKMAP?
|
|
BMI DoPhase6 ;Yes
|
|
JMP OK2Exit
|
|
;=================================================
|
|
; Phase 6 of the Linking process
|
|
; Makes use of LoadMap table to store info
|
|
; into the LINKMAP txtfile
|
|
; ($2E17)
|
|
|
|
DoPhase6
|
|
LDY #$09
|
|
JSR DisplayMsg
|
|
JSR DisplayCR
|
|
LDY #$09
|
|
JSR StoreMsg
|
|
JSR StoreCR
|
|
JSR ResetFilePos ;Reset to start of cmd line file
|
|
JSR StoreCR
|
|
JSR StoreCR
|
|
LDA #0
|
|
STA ModuleNbr
|
|
STA numSrcFiles ;reset counter
|
|
STA PageOption ;Don't output to printer
|
|
|
|
Phs6Loop
|
|
JSR AbortPause
|
|
JSR ReadOneCmd
|
|
BNE @doPN ;If non-blank & not cr, it's a PN
|
|
CMP #CR ;Is 1st char a CR?
|
|
BNE @1 ;No, a leading space, ignore it
|
|
JMP xfile ;No more directives
|
|
@1 JSR StoreCommand ;Just store command in LINKMAP file
|
|
JMP Phs6Loop ;Get another command
|
|
|
|
; Got the Pathname of a SRC file
|
|
|
|
@doPN JSR StoreCR
|
|
JSR StoreCR
|
|
LDY #$18 ;MOD ORG etc
|
|
JSR StoreMsg
|
|
LDY #$19 ;# ADR ADR etc
|
|
JSR StoreMsg
|
|
JSR StoreCR
|
|
JMP WrtLM1 ;-> proceed to start storing info
|
|
|
|
; Loop to get the PN of another src file
|
|
|
|
NxtSrcFile
|
|
JSR AbortPause
|
|
JSR ReadOneCmd
|
|
BNE WrtLM1 ;Not cr/space
|
|
CMP #CR
|
|
BEQ xfile ;No more commands => done
|
|
JSR StoreAddrs ;Set module's Addr Range
|
|
BEQ WrtLM2 ;always
|
|
|
|
; Start writing info into LINKMAP file
|
|
|
|
WrtLM1 JSR StoreSpace
|
|
LDA ModuleNbr
|
|
JSR StoreByte
|
|
JSR StoreSpace
|
|
JSR StoreSpace
|
|
|
|
LDX numSrcFiles ;Get SRC file index
|
|
WrtLM2 LDA orgAdrHi,X ;Starting Addr
|
|
JSR StoreByte
|
|
LDA orgAdrLo,X ; of this src module
|
|
JSR StoreByte
|
|
|
|
LDA #'-'
|
|
JSR StoreChar
|
|
LDA EndAddrHi,X ;Its Ending Addr
|
|
JSR StoreByte
|
|
LDA EndAddrLo,X
|
|
JSR StoreByte
|
|
JSR StoreSpace
|
|
JSR StoreSpace
|
|
|
|
LDY #0
|
|
@ploop JSR ChrGot ;Store its pathname
|
|
CMP #CR
|
|
BEQ @nxtFile
|
|
JSR StoreChar
|
|
INY
|
|
BNE @ploop
|
|
|
|
@nxtFile
|
|
JSR StoreCR
|
|
CPX numSrcFiles
|
|
BNE @nxtFile1
|
|
|
|
SED
|
|
LDA ModuleNbr
|
|
CLC
|
|
ADC #1
|
|
STA ModuleNbr
|
|
CLD
|
|
INC numSrcFiles
|
|
@nxtFile1
|
|
JMP NxtSrcFile ;Loop back for next module
|
|
|
|
xfile BIT XRefOption ;Did user ask for cross-ferencing?
|
|
BPL ExitPhase6 ;No
|
|
|
|
LDA #$80
|
|
STA PageOption
|
|
JSR doPageFeed ;Store column header details etc...
|
|
BIT SortOption ;Did we sort the LoadMap table?
|
|
BPL WrEntryRecs ;No
|
|
|
|
; Use Sorted LoadMap table
|
|
|
|
LDA #<X9100
|
|
STA Z86
|
|
LDA #>X9100 ;Points to BO LoadMap table
|
|
STA Z86+1
|
|
LMWrtLoop
|
|
JSR AbortPause
|
|
LDY #0
|
|
LDA (Z86),Y ;Get ptr to ENTRY record
|
|
STA Z88
|
|
INY
|
|
LDA (Z86),Y
|
|
STA Z88+1 ; and store it here
|
|
ORA Z88 ;EO ENTRY table?
|
|
BEQ ExitPhase6 ;Yes
|
|
|
|
JSR StoreEntryInfo ;Write details of ENTRY rec into LINKMAP
|
|
LDA #4 ;Pointer size
|
|
LDX #Z86 ; Z86++
|
|
JSR AdvNextRecZ ;Next LoadMap record
|
|
JMP LMWrtLoop
|
|
|
|
; Use ENTRY table instead of LoadMap table
|
|
|
|
WrEntryRecs
|
|
LDA #<EntryTab
|
|
STA Z88
|
|
LDA #>EntryTab
|
|
STA Z88+1
|
|
|
|
@wrLoop JSR AbortPause
|
|
LDY #0
|
|
LDA (Z88),Y ;EOT?
|
|
BEQ ExitPhase6 ;Yes
|
|
JSR StoreEntryInfo ;Store details of ENTRY rec into LINKMAP
|
|
LDX #Z88
|
|
LDA #EntryRecord.sizeof
|
|
JSR AdvNextRecZ ;Next ENTRY record
|
|
JMP @wrLoop ;Continue until EO ENTRY Table
|
|
;===============================
|
|
; Prepare to exit Linker
|
|
; Input
|
|
; Output
|
|
|
|
ExitPhase6
|
|
LDA #FF
|
|
JSR StoreChar
|
|
JSR StoreCR
|
|
LDA WriteMapRecP8+C_REFNUM ;Close LINKMAP txt file
|
|
STA CloseAnyRecP8+C_REFNUM
|
|
JSR PRODOS8
|
|
DC.B $CC ;CLOSE
|
|
DC.W CloseAnyRecP8
|
|
BEQ OK2Exit
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
OK2Exit JMP DoExit ;Do an orderly exit
|
|
;===============================
|
|
; Get ORiGin and END address of the module
|
|
; Z=0, (X)=0
|
|
; ($2F43)
|
|
|
|
StoreAddrs
|
|
LDY #$05 ;Write 5 blanks to LINKMAP
|
|
JSR StoreYSpaces
|
|
LDX numSrcFiles ;Get SRC file index (1-49)
|
|
DEX ;index previous SRC module
|
|
LDY EndAddrHi,X
|
|
LDA EndAddrLo,X
|
|
TAX
|
|
INX
|
|
BNE @1
|
|
INY
|
|
@1 STX orgAdrLo
|
|
STY orgAdrHi
|
|
|
|
LDX numSrcFiles
|
|
LDY orgAdrHi,X
|
|
LDA orgAdrLo,X
|
|
TAX
|
|
BNE @2
|
|
DEY
|
|
@2 DEX
|
|
STX EndAddrLo
|
|
STY EndAddrHi
|
|
LDX #$00
|
|
RTS
|
|
;===============================
|
|
; Store info from ENTRY record
|
|
; Input
|
|
; Output
|
|
; ($2F74)
|
|
|
|
StoreEntryInfo
|
|
JSR WrtFlag ;Store space/?
|
|
JSR StoreAddress ;Relocated addr
|
|
JSR StoreFileNum ;File #
|
|
JSR StoreSpace
|
|
JSR StoreName ;Symbolicname
|
|
JSR StoreSpace
|
|
JSR StoreRefs ;list of references
|
|
JSR StoreCR
|
|
RTS
|
|
;===============================
|
|
; Store a byte as a couple of ASCII Hex digits
|
|
; Input
|
|
; (A)=byte
|
|
|
|
StoreByte
|
|
PHA
|
|
LSR A
|
|
LSR A
|
|
LSR A
|
|
LSR A
|
|
JSR StoreHex
|
|
PLA
|
|
AND #$0F
|
|
JSR StoreHex
|
|
RTS
|
|
;===============================
|
|
; Store char into LINKMAP buffer. If char is CR, the
|
|
; entire text line will be written out to file.
|
|
; Otherwise, it will be stored into the buffer
|
|
; Input
|
|
; WrMapFIdx - Write Map file buf index
|
|
; (A) = char to store
|
|
; Output
|
|
; A,X preserved
|
|
; Y may not be used
|
|
; ($2F9C)
|
|
|
|
StoreChar
|
|
AND #$7F
|
|
STA SaveA ;Save A,X regs
|
|
STX SaveA+1
|
|
LDX MapIndex
|
|
STA MapDataBuf,X ;store in buf
|
|
INC MapIndex ;incr # of chars/buf index
|
|
CMP #CR
|
|
BNE @Rst ;Delay write
|
|
|
|
; Flush it
|
|
|
|
JSR PRODOS8
|
|
DC.B $CB ;WRITE
|
|
DC.W WriteMapRecP8
|
|
BEQ @noErrs
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@noErrs STA MapIndex ;Zero write buf index
|
|
@Rst LDX SaveA+1 ;Restore A,X regs
|
|
LDA SaveA
|
|
RTS
|
|
;===============================
|
|
; Convert a 8-bit binary value into its
|
|
; ASCII representation of 1's and 0's
|
|
; Input
|
|
; Output
|
|
; ($2FC2) - Not used
|
|
|
|
Cnv2BinStr
|
|
LDX #8
|
|
@cnvlup ASL A ;Get bit into Carry
|
|
PHA
|
|
LDA #$00
|
|
ROL A ;Catch the bit
|
|
ADC #'0' ;'0' or '1'
|
|
JSR StoreChar
|
|
PLA
|
|
DEX
|
|
BNE @cnvlup ;Next bit
|
|
RTS
|
|
;===============================
|
|
; Store a CR to LINKMAP file
|
|
; Input
|
|
; Output
|
|
; ($2FD3)
|
|
|
|
StoreCR LDA #CR
|
|
JSR StoreChar
|
|
INC LineCnt
|
|
LDA LineCnt
|
|
CMP #60
|
|
BNE @ret
|
|
JSR doPageFeed ;Write column header
|
|
@ret RTS
|
|
;===============================
|
|
; Output a column header into LINKMAP file
|
|
; Input
|
|
; Output
|
|
|
|
doPageFeed
|
|
LDA #FF ;Output a formfeed char
|
|
JSR StoreChar
|
|
LDA #3
|
|
STA LineCnt
|
|
SED
|
|
CLC
|
|
LDA #1
|
|
ADC PageCnt
|
|
STA PageCnt
|
|
CLD
|
|
BIT PageOption
|
|
BPL @1
|
|
|
|
LDY #$1A ;Write 'ADR M# SYMBOL...' header
|
|
JSR StoreMsg ; string to LINKMAP file
|
|
LDA PageCnt
|
|
JSR StoreByte
|
|
|
|
@1 JSR StoreCR
|
|
JSR StoreCR
|
|
RTS
|
|
;===============================
|
|
; Input
|
|
; Output
|
|
; ($300B)
|
|
|
|
WrtFlag
|
|
LDY #EntryRecord.flags
|
|
LDA (Z88),Y
|
|
AND #unreferenced
|
|
BEQ StoreSpace ;Use a space for referenced symbols
|
|
LDA #'?'
|
|
BNE StorChar ;Use a Qn mark for unreferenced ones
|
|
;===============================
|
|
; Store a space into LINKMAP txt file buffer
|
|
|
|
StoreSpace
|
|
LDA #SPACE
|
|
StorChar
|
|
JSR StoreChar
|
|
RTS
|
|
;===============================
|
|
; Input
|
|
; (A)=$00-$0F
|
|
; Output
|
|
|
|
StoreHex
|
|
ORA #'0'
|
|
CMP #'9'+1
|
|
BCC @1
|
|
ADC #$06
|
|
@1 JSR StoreChar
|
|
RTS
|
|
;===============================
|
|
; Store a list of references to a relocated addr
|
|
; into the LINKMAP file
|
|
; $40 set -> not referenced by any module
|
|
; Input
|
|
; (Z88) - Ptr to an ENTRY record
|
|
; Output
|
|
; Trashed
|
|
; (xtrnRecP) - Ptr to an EXTRN record
|
|
; ($3029)
|
|
|
|
StoreRefs
|
|
LDY #EntryRecord.flags
|
|
LDA (Z88),Y
|
|
AND #unreferenced
|
|
BEQ @1
|
|
LDY #$16
|
|
JSR StoreMsg
|
|
RTS
|
|
|
|
@1 LDA Z88 ;NB. (Z88) is ptr to ENTRY record
|
|
STA xtrnRecP ;Use this zpage temporarily
|
|
LDA Z88+1
|
|
STA xtrnRecP+1
|
|
|
|
LDY #EntryRecord.head ;Start with the first node
|
|
@nloop LDA (xtrnRecP),Y
|
|
PHA ;Get ptr to "next" EXTRN record
|
|
INY
|
|
LDA (xtrnRecP),Y
|
|
STA xtrnRecP+1
|
|
PLA
|
|
STA xtrnRecP
|
|
ORA xtrnRecP+1
|
|
BEQ @done ;NULL => end of singly linked list
|
|
|
|
LDY #XtrnRecord.fileNum
|
|
LDA (xtrnRecP),Y ;(A)=# to be converted
|
|
LDY #0 ;ten's digit
|
|
JSR Cnv2S
|
|
JSR StoreSpace
|
|
LDA MapIndex ;# of bytes in Map file's data buf
|
|
LDY #0
|
|
CMP #77 ; must not exceed this number
|
|
BCC @nloop ;Next node
|
|
|
|
JSR StoreCR
|
|
LDY #26 ;# of spaces
|
|
JSR StoreYSpaces
|
|
LDY #0
|
|
JMP @nloop ;Next Node in linked list
|
|
@done RTS
|
|
;===============================
|
|
; Store REL file # as a 2-byte ASC char in LINKMAP file
|
|
; Input
|
|
; Output
|
|
; ($3073)
|
|
|
|
StoreFileNum
|
|
LDY #EntryRecord.fileNum
|
|
LDA (Z88),Y ;REL file #
|
|
LDY #0 ;This should be the entry point
|
|
Cnv2S CMP #10
|
|
BCC @1
|
|
SEC
|
|
SBC #10
|
|
INY ;TEN'S digit
|
|
JMP Cnv2S
|
|
|
|
@1 PHA ;UNIT'S digit
|
|
TYA
|
|
ORA #'0'
|
|
JSR StoreChar
|
|
PLA
|
|
ORA #'0'
|
|
JSR StoreChar
|
|
RTS
|
|
;===============================
|
|
; Store ENTRY record's symbolic name
|
|
; Input
|
|
; (Z88) - ptr to ENTRY record
|
|
; Output
|
|
; ($3092)
|
|
|
|
StoreName
|
|
LDY #EntryRecord.symbolName
|
|
LDA (Z88),Y ;Get its len byte
|
|
CMP #SymbolRecord.sizeof
|
|
BCC @1
|
|
|
|
LDA #SymbolRecord.sizeof-1 ;At most 15 chars
|
|
@1 TAX
|
|
@mloop INY
|
|
LDA (Z88),Y ;symbolname
|
|
JSR StoreChar
|
|
DEX
|
|
BNE @mloop
|
|
|
|
STY SYMLEN ;# of chars stored so far
|
|
SEC
|
|
LDA #SymbolRecord.sizeof
|
|
SBC SYMLEN
|
|
TAY ;# of spaces to store
|
|
|
|
; Enter here with (Y)=# of spaces to store
|
|
|
|
StoreYSpaces
|
|
LDA #SPACE
|
|
JSR StoreChar
|
|
DEY
|
|
BNE StoreYSpaces
|
|
RTS
|
|
;===============================
|
|
; Store Relocated address in LINKMAP file
|
|
; Input
|
|
; (Z88) - ptr to an ENTRY record
|
|
; Output
|
|
; ($30B9)
|
|
|
|
StoreAddress
|
|
LDY #EntryRecord.relAddr+1
|
|
LDA (Z88),Y
|
|
JSR StoreByte
|
|
DEY
|
|
LDA (Z88),Y
|
|
JSR StoreByte
|
|
JSR StoreSpace
|
|
RTS
|
|
;===============================
|
|
; Store command line including terminating CR
|
|
; Input
|
|
; (cp)
|
|
; Output
|
|
; ($30CA)
|
|
|
|
StoreCommand
|
|
LDY #0
|
|
@loop LDA (cp),Y
|
|
AND #$7F
|
|
JSR StoreChar
|
|
INY
|
|
CMP #CR
|
|
BNE @loop
|
|
RTS
|
|
;===============================
|
|
; If the flag of an RLD entry of SRC file indicates it is an
|
|
; (a) ENTRY symbol, calc relocated addr
|
|
; (b) EXTRN symbol, get relocated addr
|
|
; fr its associated ENTRY rec &
|
|
; we must modify the
|
|
; RLD & EXTRN recs
|
|
; Input
|
|
; RLDFlags
|
|
; Output
|
|
; RelAdr - value of relocated addr
|
|
; ($30D9)
|
|
|
|
GetRelAdr
|
|
LDA RLD_Flags
|
|
AND #external ;Is EXTERN symbol?
|
|
BNE @xtrn ;Yes
|
|
|
|
LDA RelAdr ;This is equivalent to a subtraction
|
|
CLC
|
|
ADC NegSrcORG ;2's complement of
|
|
STA RelAdr
|
|
LDA RelAdr+1
|
|
ADC NegSrcORG+1 ; Origin in SRC file
|
|
STA RelAdr+1
|
|
|
|
LDA RelAdr
|
|
CLC
|
|
ADC CurrORG
|
|
STA RelAdr
|
|
LDA RelAdr+1
|
|
ADC CurrORG+1
|
|
STA RelAdr+1
|
|
RTS
|
|
|
|
; EXTRN symbol
|
|
|
|
@xtrn LDY ModuleNbr ;Get ptr to the
|
|
LDA srcModTabLo,Y ; first EXTRN rec
|
|
STA xtrnRecP ; of the SRC file
|
|
LDA srcModTabHi,Y
|
|
STA xtrnRecP+1
|
|
|
|
; Search thru the EXTRN recs for the EXTRN symbol #.
|
|
; NB. A hit is guaranteed during the search
|
|
; through the sub-array of EXTRN recs
|
|
|
|
LDA #0
|
|
STA RelAdr
|
|
STA RelAdr+1
|
|
LDY #RLDRecord.esdNum
|
|
LDA (srcP),Y ;Get the EXTRN symbol #
|
|
@srch LDY #XtrnRecord.symbolNum
|
|
CMP (xtrnRecP),Y
|
|
BEQ @hit ;Matched
|
|
JSR AdvNxtExtrn
|
|
JMP @srch ;Try next EXTRN rec
|
|
|
|
@hit LDY #XtrnRecord.flags
|
|
LDA (xtrnRecP),Y
|
|
AND #$FF-unreferenced ;Clear the bit
|
|
STA (xtrnRecP),Y
|
|
AND #undefined ;Is the symbolicname still undefined?
|
|
BNE @CkFtype ;Yes
|
|
|
|
LDY #XtrnRecord.entryPtr
|
|
LDA (xtrnRecP),Y ;Get ptr to associated
|
|
STA Z82 ; ENTRY record
|
|
INY
|
|
LDA (xtrnRecP),Y
|
|
STA Z82+1
|
|
|
|
LDY #EntryRecord.relAddr
|
|
LDA (Z82),Y
|
|
STA RelAdr
|
|
INY
|
|
LDA (Z82),Y
|
|
STA RelAdr+1
|
|
|
|
BIT WhichType ;Is it OBJECT file relocatable?
|
|
BPL @doRTS ;No, just ret
|
|
|
|
; The OBJECT file is of type REL so
|
|
; we need to patch the curr RLD rec
|
|
|
|
LDY #RLDRecord.flags
|
|
LDA (srcP),Y ;Mark symbol is no longer an EXTRN-type
|
|
AND #$FF-external
|
|
STA (srcP),Y ; since symbolicname is defined
|
|
LDY #RLDRecord.low8bits
|
|
AND #%11000000
|
|
CMP #$40 ;lo 8 bits?
|
|
BNE @1 ;=>hi 8 bits
|
|
|
|
LDA RelAdr ;Use lo 8-bits to patch
|
|
DC.B $2C
|
|
@1 LDA #0 ;Use a zero to patch
|
|
STA (srcP),Y ; the RLD record
|
|
JMP @doRTS ;Done
|
|
|
|
; The symbolicname had not been defined
|
|
|
|
@CkFtype
|
|
BIT WhichType ;Is OBJECT file of type REL?
|
|
BPL @doRTS ;No
|
|
|
|
; The target OBJECT file is REL so
|
|
; patch the RLD entry of the SRC file
|
|
; Once again we assume the RLD is < 5K
|
|
; since the patched RLD is only written out
|
|
; when processing of the SRC file is complete
|
|
|
|
LDY #XtrnRecord.externNum
|
|
LDA (xtrnRecP),Y ; Take the EXTRN # assigned by the Linker
|
|
LDY #RLDRecord.esdNum ; & replace that in the RLD rec which
|
|
STA (srcP),Y ; was assigned by the Assembler
|
|
@doRTS RTS
|
|
;===============================
|
|
; Setup to open and write a TempRLD binary file;
|
|
; any old file will be deleted prior to this.
|
|
; Input
|
|
; Output
|
|
; Write2P+c.refNum - RN to write tempRLD file
|
|
; ($317A)
|
|
|
|
OpenTmpRLD
|
|
LDY TempRLDName
|
|
@cloop LDA TempRLDName,Y
|
|
STA pathNameBuf,Y
|
|
DEY
|
|
BPL @cloop
|
|
|
|
JSR PRODOS8
|
|
DC.B $C1
|
|
DC.W DestroyRecP8 ;DESTROY
|
|
LDA #BIN_type
|
|
STA CreateRecP8+C_FILEID
|
|
JSR PRODOS8
|
|
DC.B $C0 ;CREATE
|
|
DC.W CreateRecP8
|
|
BEQ @1
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@1 JSR PRODOS8
|
|
DC.B $C8 ;OPEN
|
|
DC.W Open2RecP8
|
|
BEQ @2
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@2 LDA Open2RecP8+C_OUTREF
|
|
STA WriteTmpRecP8+C_REFNUM ;write RN of tempRLD file
|
|
RTS
|
|
;===============================
|
|
; Append a patched RLD of curr SRC file to the tempRLD file
|
|
; Input
|
|
; Output
|
|
; ($31AE)
|
|
|
|
AppendTmpRLD
|
|
BIT WhichType ;Is OBJECT file of type REL?
|
|
BPL doRTS2 ;No
|
|
|
|
SEC
|
|
LDA srcP
|
|
SBC #<srcDataBuf
|
|
STA WriteTmpRecP8+C_REQCNT ;writelen
|
|
LDA srcP+1
|
|
SBC #>srcDataBuf
|
|
STA WriteTmpRecP8+C_REQCNT+1
|
|
|
|
; Write to tempRLD file
|
|
|
|
WrtTempRld
|
|
JSR PRODOS8
|
|
DC.B $CB ;WRITE
|
|
DC.W WriteTmpRecP8
|
|
BEQ doRTS2
|
|
JSR ErrHandler ;Don't come back
|
|
doRTS2 RTS
|
|
;===============================
|
|
; Open the LINKMAP file and set the
|
|
; file posn to its EOF
|
|
;
|
|
; Input
|
|
; Output
|
|
; ($31CD)
|
|
|
|
OpenMapAppend
|
|
JSR MoveMapName ;Set PN to LINKMAP
|
|
JSR PRODOS8
|
|
DC.B $C8 ;OPEN
|
|
DC.W Open2RecP8
|
|
BEQ @1
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@1 LDA Open2RecP8+C_OUTREF
|
|
STA WriteMapRecP8+C_REFNUM
|
|
STA EOFRecP8+C_REFNUM
|
|
JSR PRODOS8
|
|
DC.B $D1 ;GET_EOF
|
|
DC.W EOFRecP8
|
|
BEQ @2
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@2 JSR PRODOS8
|
|
DC.B $CE ;SET_MARK
|
|
DC.W EOFRecP8 ;Set to EO LINKMAP file
|
|
BEQ @ret
|
|
JSR ErrHandler ;Don't come back
|
|
@ret RTS
|
|
;===============================
|
|
; Check if cmd line is an ALN Command/Directive
|
|
; Input
|
|
; Output
|
|
; Z=1 & C=0 - yes
|
|
; ($31FB)
|
|
|
|
IsAlign
|
|
JSR ShowLineBuf
|
|
JSR SkipSpaces
|
|
JSR ChkDirective
|
|
BCS @ret ;Unknown cmd
|
|
CMP #5
|
|
CLC
|
|
@ret RTS
|
|
;=================================================
|
|
; Load EDASM's Editor. EdAsm's Command Interpreter
|
|
; is always resident in memory.
|
|
; ($320A)
|
|
;=================================================
|
|
|
|
LoadEditor
|
|
JSR PrefixEdAsm ;Set prefix to EdAsm's dir
|
|
BCC @load
|
|
LDA #$FE ;EdAsm Command Interpreter's error #
|
|
JSR PrintError
|
|
|
|
LDY #0
|
|
LDX EdAsmDir ;Get its len byte
|
|
@loop LDA EdAsmDir+1,Y
|
|
JSR DisplayChar
|
|
INY
|
|
DEX
|
|
BNE @loop
|
|
|
|
JSR DisplayCR
|
|
LDA #$FD ;Output thru EdAsm's Interpreter
|
|
JSR PrintError ; display error rtn
|
|
|
|
@key1 LDA KBD
|
|
BPL @key1
|
|
BIT KBDSTROBE ;Clear it
|
|
CMP #CR+$80
|
|
BNE @key1
|
|
JSR DisplayCR
|
|
JMP LoadEditor ;Try again
|
|
|
|
@load LDA #<LoadAdrEditor
|
|
STA ReadEditorRecP8+C_DATABUF
|
|
LDA #>LoadAdrEditor
|
|
STA ReadEditorRecP8+C_DATABUF+1
|
|
|
|
LDA #<$2000
|
|
STA ReadEditorRecP8+C_REQCNT
|
|
LDA #>$2000
|
|
STA ReadEditorRecP8+C_REQCNT+1
|
|
JSR PRODOS8
|
|
DC.B $C8 ;OPEN
|
|
DC.W OpenEditorRecP8
|
|
BEQ @opened
|
|
JSR FatalError
|
|
|
|
@opened LDA OpenEditorRecP8+C_OUTREF ;file is there
|
|
STA ReadEditorRecP8+C_REFNUM
|
|
JSR PRODOS8 ;READ
|
|
DC.B $CA
|
|
DC.W ReadEditorRecP8
|
|
BEQ @read
|
|
JSR FatalError
|
|
|
|
@read LDA ReadEditorRecP8+C_REFNUM
|
|
STA CloseAnyRecP8+C_REFNUM ;file now in memory
|
|
JSR PRODOS8
|
|
DC.B $CC ;CLOSE
|
|
DC.W CloseAnyRecP8
|
|
BEQ @setup
|
|
JMP FatalError
|
|
|
|
@setup JSR S2CurrPfx
|
|
BCS FatalError
|
|
;=================================================
|
|
; Setup memory map for the EdAsm's Editor Module
|
|
; Memory pages mark as used: $9B-$A7, $B1-$B8, $BF
|
|
; EDASM's Interpreter is at $B100-$BD00
|
|
;=================================================
|
|
|
|
LDA #%11111111 ;$FF: pages $A0-A7 are used
|
|
STA MemoryMap+20
|
|
LDA #%00011111 ;$1F: free pages $98-$9A
|
|
STA MemoryMap+19
|
|
LDA #%01111111 ;$7F: free pages $B0
|
|
STA MemoryMap+22
|
|
LDA #%10000001 ;$81: free pages $B9-$BE
|
|
STA MemoryMap+23
|
|
|
|
; TxtBgn=$0801
|
|
|
|
LDA #CR
|
|
DEC TxtBgn ;Put a CR @ mem locations
|
|
LDY #$00
|
|
STA (TxtBgn),Y
|
|
INC TxtBgn ; $0800 and $0801
|
|
STA (TxtBgn),Y
|
|
RTS
|
|
;=================================================
|
|
; ($32A4)
|
|
|
|
FatalError
|
|
STA $FE ;Save err code
|
|
TSX
|
|
STX $FF ;Save stack ptr here
|
|
|
|
LDX #$80
|
|
TXS
|
|
LDA RDROM2 ;Read ROM; no write
|
|
JSR SETKBD ;reset input to keyboard
|
|
JSR SETVID ;reset output to screen
|
|
JSR HOME ;clear screen and home cursor
|
|
JSR PRERR ;print "ERR"
|
|
JMP MON ;std monitor entry w/beep
|
|
;=================================================
|
|
; Set prefix to EDASM's dir
|
|
;=================================================
|
|
|
|
PrefixEdAsm
|
|
JSR PRODOS8
|
|
DC.B $C6 ;SET_PREFIX
|
|
DC.W EdAsmPfxRecP8
|
|
RTS
|
|
;=================================================
|
|
; Set prefix to current prefix
|
|
;=================================================
|
|
|
|
S2CurrPfx
|
|
JSR PRODOS8
|
|
DC.B $C6 ;SET_PREFIX
|
|
DC.W SetCurrPfxRecP8
|
|
RTS
|
|
;=================================================
|
|
; EDASM Editor's P8 parameter blocks
|
|
;=================================================
|
|
|
|
EditorName
|
|
STR 'EDASM.ED'
|
|
DC.B $00
|
|
|
|
; Use to open EdAsm's Editor
|
|
OpenEditorRecP8
|
|
DC.B $03
|
|
DC.W EditorName
|
|
DC.W XA900 ;1024-byte buffer required by P8
|
|
DC.B $CB ;ref #
|
|
|
|
; Use to read EdAsm's Editor into memory
|
|
ReadEditorRecP8
|
|
DC.B $04
|
|
DC.B $D0
|
|
DC.W $A0A0
|
|
DC.W $A0D3 ;Caller must set this
|
|
DC.W $CBA0 ;actual len read (ignore)
|
|
|
|
; Use to set prefix to EdAsm's directory on disk
|
|
EdAsmPfxRecP8
|
|
DC.B $01
|
|
DC.W EdAsmDir
|
|
|
|
SetCurrPfxRecP8
|
|
DC.B $01
|
|
DC.W currPfxBuf
|
|
;=================================================
|
|
; Move a block of src code fr one mem location to
|
|
; another mem location (but not including byte @
|
|
; location Z80)
|
|
; Input
|
|
; srcP - Start addr of data
|
|
; Z80 - End addr of data
|
|
; Z82 - Destination addr
|
|
; Output
|
|
; (Z82)
|
|
; (srcP)
|
|
; (Y)=0
|
|
|
|
MoveData
|
|
LDY #0
|
|
@mvLup3 LDA (srcP),Y
|
|
STA (Z82),Y
|
|
INC Z82
|
|
BNE @1
|
|
INC Z82+1
|
|
@1 LDA srcP ;Copy until
|
|
CMP Z80
|
|
LDA srcP+1
|
|
SBC Z80+1 ; (Z80)=(srcP)
|
|
INC srcP
|
|
BNE @2
|
|
INC srcP+1
|
|
@2 BCC @mvLup3
|
|
RTS
|
|
;=================================================
|
|
; These rtns adjust the ptrs to the next
|
|
; element (record) of their respective arrays (table)
|
|
; ($3307)
|
|
|
|
AdvNxtExtrn
|
|
PHA ;Save Acc temporarily
|
|
LDA #XtrnRecord.sizeof
|
|
LDX #xtrnRecP
|
|
JMP AdvNextRec
|
|
|
|
AdvNxtEntry
|
|
PHA
|
|
LDA #EntryRecord.sizeof
|
|
LDX #entRecP
|
|
JMP AdvNextRec
|
|
|
|
AdvNxtSymbol
|
|
PHA ;Save Acc temporarily
|
|
LDA #SymbolRecord.sizeof
|
|
LDX #symP
|
|
;
|
|
; (A)=# to add to pointer stored in 2 consecutive mem locations
|
|
; (X)=offset into zero page
|
|
|
|
AdvNextRec
|
|
CLC
|
|
ADC $00,X
|
|
STA $00,X
|
|
LDA #0
|
|
ADC $00+1,X
|
|
STA $00+1,X
|
|
PLA ;Restore Acc
|
|
RTS
|
|
;===============================
|
|
; Same logic as above except (X) can be an index into
|
|
; ANY zeropage location
|
|
; Input
|
|
; (A)=# to add to pointer stored in 2 consecutive mem locations
|
|
; (X)=offset into zero page
|
|
;
|
|
; Output
|
|
|
|
AdvNextRecZ
|
|
PHA
|
|
JMP AdvNextRec
|
|
;===============================
|
|
; Ref pg 229 ProDOS Assembler Tools Manual
|
|
; Advance srcP to next ESD record
|
|
; Input
|
|
; Output
|
|
; (srcP) = Pointing @ next ESD record or $00
|
|
; X - unchanged
|
|
|
|
NxtESDRec
|
|
LDY #0
|
|
@loop LDA (srcP),Y ;ENTRY/EXTRN symbolic name
|
|
BPL @1 ;Got last char
|
|
INY
|
|
JMP @loop
|
|
|
|
@1 INY ;Index past the last char
|
|
INY
|
|
INY
|
|
INY ;Now indexing next ESD rec (if any)
|
|
TYA
|
|
CLC
|
|
ADC srcP ;srcP now pointing @ next ESD
|
|
STA srcP
|
|
LDA #0
|
|
ADC srcP+1 ; record in the curr src file
|
|
STA srcP+1
|
|
RTS
|
|
;=================================================
|
|
; There are 3 entry points in this part of the code
|
|
; Input
|
|
; OpenSrcRecP8+c.outRef - file ref # of src (REL) file
|
|
; Output
|
|
; C=0 - Last chunk of data had been read
|
|
; C=1 & (A)=$10 - Not EOF
|
|
; C=1 & (A)=$4C - EOF
|
|
; (srcP) points to BO srcDataBuf
|
|
; ($3348)
|
|
;=================================================
|
|
ReadMax
|
|
LDA OpenSrcRecP8+C_OUTREF
|
|
STA RWFileRecP8+C_REFNUM
|
|
|
|
; Use this entry point to attempt to read a fixed chunk
|
|
; of data (equal to the size of the data buffer) fr a
|
|
; ANY file into the beginning of the Data Buffer ($0C00)
|
|
; (srcP) points to BO of this data buf (srcDataBuf)
|
|
|
|
ReadChunk
|
|
LDA #<srcDataBuf
|
|
STA RWFileRecP8+C_DATABUF
|
|
LDA #>srcDataBuf
|
|
STA RWFileRecP8+C_DATABUF+1
|
|
|
|
LDA #<FileDataBufSiz ;# of bytes to be read=5K
|
|
STA RWFileRecP8+C_REQCNT
|
|
LDA #>FileDataBufSiz
|
|
STA RWFileRecP8+C_REQCNT+1
|
|
|
|
; Use this entry point to read a chunk of data fr ANY file.
|
|
; Caller must set the # of bytes to read (reqCnt) in
|
|
; RWFile parm block.
|
|
; (srcP) is set to point to start of srcDataBuf ($0C00)
|
|
|
|
GetMoreCode
|
|
LDA #<srcDataBuf
|
|
STA srcP
|
|
LDA #>srcDataBuf
|
|
STA srcP+1
|
|
JSR PRODOS8
|
|
DC.B $CA ;READ
|
|
DC.W RWFileRecP8
|
|
BNE ReadErrs ;If EOF, (A)=$4C and C=1
|
|
|
|
; After a successful read, at most NumRead = Request Length
|
|
; For this case, there may be more data to be read
|
|
|
|
LDA RWFileRecP8+C_TRANSCNT+1 ;If actual # of bytes read
|
|
CMP RWFileRecP8+C_REQCNT+1 ; = requested len then
|
|
BNE LastChunk ; it may not be EOF since
|
|
LDA RWFileRecP8+C_TRANSCNT
|
|
CMP RWFileRecP8+C_REQCNT
|
|
BEQ GotMore ; there may be more data to be read
|
|
|
|
LastChunk
|
|
CLC ;NOT =, ==> last chunk of data read
|
|
RTS ; since NumRead < ReqLen
|
|
GotMore
|
|
LDA #$10 ;= but not EOF, so use $10 to flag it
|
|
ReadErrs
|
|
SEC
|
|
RTS
|
|
;=================================================
|
|
; Print Message
|
|
; The terminating char of each message in this table
|
|
; is a backslash
|
|
; Input
|
|
; (Y) = index into Message Table whose addresses
|
|
; are split into 2 sub-tables
|
|
; Output
|
|
; ($3388)
|
|
|
|
DisplayMsg
|
|
LDA MsgTabLo,Y ;(Y) = message #
|
|
STA msgP
|
|
LDA MsgTabHi,Y
|
|
STA msgP+1
|
|
LDY #0
|
|
@sloop LDA (msgP),Y
|
|
CMP #'\' ;terminator
|
|
BEQ @done
|
|
JSR CharOut
|
|
INY
|
|
JMP @sloop
|
|
@done RTS
|
|
;=================================================
|
|
; Setup the pathname buffer using a cmd line
|
|
; Input
|
|
; Output
|
|
; ($33A2)
|
|
|
|
GetSrcPathName
|
|
LDY #-1 ;=0 on fall thru
|
|
@mvLoop INY
|
|
LDA (cp),Y
|
|
AND #$7F ;Ensure filename std ASCII
|
|
STA pathNameBuf+1,Y
|
|
CMP #CR ;CR
|
|
BNE @mvLoop
|
|
STY pathNameBuf ;len byte
|
|
RTS
|
|
;=================================================
|
|
; Open a src file by getting its filename from
|
|
; the command file.
|
|
; Get len of its code image and compute the
|
|
; addr past its last byte.
|
|
;
|
|
; Input
|
|
;
|
|
; Output
|
|
; C=1 - err
|
|
; (A)=err code
|
|
; (Z9E)=$80 - src file will be read but EXTRN records will
|
|
; not be created fr its ESD. Its code will not be included into
|
|
; the OBJECT file. ENTRY and Symbol records are created.
|
|
; This may be used to facilitate overlays rather than
|
|
; hand-patching JSR/JMP etc addresses
|
|
; Todo: Check it
|
|
; NB: Symbol records are created fr info in the
|
|
; appended ESD of all SRC files.
|
|
; ($33B4)
|
|
|
|
OpenSrcFile
|
|
LDY #0
|
|
STY Z9E
|
|
LDA (cp),Y
|
|
CMP #'*'
|
|
BNE @2
|
|
INC cp ;Skip to next char
|
|
BNE @1
|
|
INC cp+1
|
|
@1 LDA #$80 ;Flag code from this SRC file
|
|
STA Z9E ; will NOT be included in OBJ file
|
|
|
|
@2 JSR GetSrcPathName ;First get the SRC file name
|
|
JSR PRODOS8
|
|
DC.B $C8 ;OPEN
|
|
DC.W OpenSrcRecP8
|
|
BNE @bad
|
|
|
|
JSR PRODOS8
|
|
DC.B $C4 ;GET_FILE_INFO
|
|
DC.W GetFileInfoRecP8
|
|
BNE @bad
|
|
|
|
LDA #$11 ;Anticipate a filetype match
|
|
LDY srcType ;Check its filetype
|
|
CPY #REL_type
|
|
BNE @bad ;filetype mismatch
|
|
|
|
LDA OpenSrcRecP8+C_OUTREF ;Prepare to read 1st 2 bytes of this
|
|
STA ReadCodeLenRecP8+C_REFNUM ; file which is len of code image
|
|
JSR PRODOS8 ;READ
|
|
DC.B $CA
|
|
DC.W ReadCodeLenRecP8
|
|
BNE @bad
|
|
|
|
LDA srcCodeLen
|
|
CLC
|
|
ADC srcORG ;Value of last ORG in this SRC file
|
|
STA objCurrSize
|
|
LDA srcCodeLen+1
|
|
ADC srcORG+1
|
|
STA objCurrSize+1 ;This is actually current size of obj file
|
|
|
|
LDA srcORG ;Perform 2's complement of the
|
|
EOR #$FF
|
|
STA NegSrcORG ; the last recorded ORG addr of SRC file
|
|
LDA srcORG+1
|
|
EOR #$FF
|
|
STA NegSrcORG+1
|
|
INC NegSrcORG
|
|
BNE @good
|
|
INC NegSrcORG+1
|
|
@good CLC
|
|
RTS
|
|
@bad SEC
|
|
RTS
|
|
;===============================
|
|
; Read in a line of text from command file
|
|
; See description below
|
|
; ($3421)
|
|
|
|
ReadOneCmd
|
|
JSR PRODOS8
|
|
DC.B $CA ;READ
|
|
DC.W ReadCmdRecP8
|
|
BEQ ResetCharPos ;Set cp to start of cmdline buf
|
|
|
|
CMP #$4C ;Is it EOF?
|
|
BEQ @ok ;Yes
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
@ok JSR ResetFilePos ;Reset file posn to BO SRC file
|
|
LDA #CR ;Store CR @ BO buffer to
|
|
STA CmdLineBuf ; denote an empty (blank) line
|
|
JMP ResetCharPos ;Set cp to point @ cmd line buf
|
|
;===============================
|
|
; Reset file position to start of the command file
|
|
; Output
|
|
; cp - ptr to 1st char of Cmd Line
|
|
; (A) - 1st char
|
|
; Z=1 - 1st char is CR/SPACE
|
|
; Z=0 - Otherwise
|
|
; ($343B)
|
|
|
|
ResetFilePos
|
|
JSR PRODOS8
|
|
DC.B $CE ;SET_MARK
|
|
DC.W MarkCmdRecP8
|
|
BEQ ResetCharPos
|
|
JSR ErrHandler ;Don't come back
|
|
|
|
ResetCharPos
|
|
LDA #<CmdLineBuf
|
|
STA cp
|
|
LDA #>CmdLineBuf
|
|
STA cp+1
|
|
|
|
LDY #0
|
|
LDA (cp),Y ;Get 1st char of cmd line
|
|
CMP #SPACE ;Z=1 if space
|
|
BEQ @doRTS
|
|
CMP #CR ;Z=1 if CR
|
|
@doRTS RTS
|
|
;=================================================
|
|
; ($3459)
|
|
; Close any type of file
|
|
; Input
|
|
; (A)=file ref #
|
|
;
|
|
; Output
|
|
|
|
CloseAnyFile
|
|
STA CloseAnyRecP8+C_REFNUM
|
|
JSR PRODOS8
|
|
DC.B $CC ;CLOSE
|
|
DC.W CloseAnyRecP8
|
|
BEQ @doRTS
|
|
JSR ErrHandler ;Don't come back
|
|
@doRTS RTS
|
|
;===============================
|
|
; Display contents of the Linker's Command Line Buffer
|
|
;
|
|
; Input
|
|
; cp - ptr to the cmdline buf
|
|
; (A) & (P) are preserved
|
|
; ($3466)
|
|
|
|
ShowLineBuf
|
|
PHP ;Save Status reg
|
|
PHA ;Save char
|
|
LDA #SPACE
|
|
JSR CharOut
|
|
JSR CharOut
|
|
JSR CharOut
|
|
JSR CharOut
|
|
JSR CharOut
|
|
|
|
LDY #0
|
|
@loop LDA (cp),Y
|
|
AND #$7F
|
|
JSR CharOut
|
|
INY
|
|
CMP #CR ;If not terminating CR,
|
|
BNE @loop ; display next char
|
|
PLA
|
|
PLP
|
|
RTS
|
|
;=================================================
|
|
; Parse directive field
|
|
; Input
|
|
; cp - pointing @ 1st char of cmdline's
|
|
; directive field
|
|
; Output
|
|
; C=0, (A)-index into JMP table
|
|
; C=1 - Unknown command
|
|
; ($348C)
|
|
;=================================================
|
|
|
|
ChkDirective
|
|
LDX #-1
|
|
NxtDrtv LDY #0
|
|
@cmLoop INX
|
|
LDA DirectivesTab,X
|
|
BEQ @err ;EOT
|
|
LDA (cp),Y
|
|
CMP DirectivesTab,X
|
|
BEQ @1 ;Got a match
|
|
CPY #3 ;Did we have a 3-char match?
|
|
BNE @skip ;No, try next entry
|
|
CMP #CR ;EO cmd line?
|
|
BEQ @gotHit ;Yes
|
|
@1 INY ;bump index to next char
|
|
CPY #4
|
|
BCC @cmLoop
|
|
BEQ @gotHit ;All chars match including trailing space
|
|
|
|
@skip CPY #3
|
|
BEQ NxtDrtv ;Loop back to check another entry
|
|
INX
|
|
INY
|
|
BNE @skip ;Skip rest of entry
|
|
|
|
@err LDY #$1B ;Unknown command
|
|
JSR DisplayMsg
|
|
SEC
|
|
RTS
|
|
|
|
@gotHit TXA ;compute index
|
|
LSR A
|
|
LSR A
|
|
CLC
|
|
RTS
|
|
;=================================================
|
|
; Start fr beginning of Cmd Line, skip blanks
|
|
; Output
|
|
; Z=1 - CR/SPACE
|
|
|
|
SkipSpaces
|
|
LDY #0
|
|
@sloop LDA (cp),Y
|
|
CMP #SPACE
|
|
BNE AdvCP
|
|
INY
|
|
BNE @sloop
|
|
|
|
; In case we can't find a non-blank, fall
|
|
; thru to start searching fr the 2nd char
|
|
; Output
|
|
; (Y) - indexing the 1st non-blank
|
|
; (A) - CR or blank
|
|
|
|
WhiteSpc
|
|
LDY #0
|
|
@loop INY
|
|
LDA (cp),Y
|
|
CMP #SPACE
|
|
BEQ @done
|
|
CMP #CR
|
|
BNE @loop
|
|
@done RTS ;Z=1 if CR/SPACE
|
|
|
|
;=================================================
|
|
; Advance cmd line buffer pointer (cp)
|
|
; Input
|
|
; (Y) - # of chars to advance
|
|
; Output
|
|
; (Y) = 0
|
|
; ($34D9)
|
|
|
|
AdvCP
|
|
TYA
|
|
CLC
|
|
ADC cp
|
|
STA cp
|
|
BCC @1
|
|
INC cp+1
|
|
@1 LDY #0
|
|
RTS
|
|
;===============================
|
|
; These rtns transfer control
|
|
; the monitor's I/O handlers
|
|
|
|
GetLine BIT RDROM2 ;Read ROM; no write
|
|
JMP GETLN ;Use MON's Input line w/prompt
|
|
|
|
DisplayCR
|
|
BIT RDROM2 ;Read ROM; no write
|
|
JMP CROUT ;Issue a carriage return
|
|
|
|
DisplayChar
|
|
BIT RDROM2 ;Read ROM; no write
|
|
JMP COUT ;As set by EdAsm's Interpreter
|
|
;=================================================
|
|
; Input
|
|
; (A)=char to display
|
|
; Preserved
|
|
; (A)
|
|
|
|
CharOut
|
|
PHA ;Save char
|
|
CMP #'a'
|
|
BCC @1
|
|
CMP #'z'+1
|
|
BCS @1
|
|
AND #$DF ;to uppercase
|
|
|
|
@1 ORA #$80 ;ensure msb on
|
|
JSR DisplayChar ;Calls actual output rtn
|
|
PLA
|
|
PHA
|
|
CMP #CR
|
|
BNE @2
|
|
JSR AbortPause
|
|
@2 PLA
|
|
RTS
|
|
;===============================
|
|
; Evaluate operand field
|
|
; No fancy stuff like * / + -
|
|
; ($3513)
|
|
|
|
EvalExpr
|
|
LDY #0
|
|
STY Value16 ;Zero the value
|
|
STY Value16+1
|
|
DEY ;=-1 cos we are going to incr
|
|
|
|
JSR ChrGet ; Y-reg b4 getting char fr buf
|
|
CMP #'$'
|
|
BNE Dec2Int ;Decimal str
|
|
|
|
; Convert str representing a hexdec value into an integer
|
|
|
|
Hex2Int JSR ChrGet
|
|
BEQ doRTS3 ;cr/space
|
|
JSR IsCharHex ;Is char hexdec?
|
|
BCS SYNERR1 ;No
|
|
JSR ShiftHexDec ;Accomodate the incoming digit
|
|
BCC Hex2Int ;Process next char
|
|
BCS SYNERR1
|
|
doRTS3 RTS
|
|
|
|
; Not referenced
|
|
|
|
PLA ;WHAT'S this?
|
|
|
|
SYNERR1 JSR CmdSynErr ;Syntax err
|
|
|
|
;=================================================
|
|
; Convert string representation of a decimal value to an integer
|
|
;
|
|
; Input
|
|
; Output
|
|
; ($3537)
|
|
;=================================================
|
|
|
|
Dec2Int
|
|
DEY
|
|
@cnv1 JSR ChrGet
|
|
BEQ doRTS3 ;If cr/space, ret
|
|
JSR IsCharDec ;Is it numeric?
|
|
BCS SYNERR1 ;No, err
|
|
JSR ShiftDecimal ;Accomodate the incoming digit
|
|
BCC @cnv1 ;Get next char
|
|
BCS SYNERR1 ;Always
|
|
|
|
ShiftDecimal
|
|
JSR MUL2
|
|
BCS @ovflw3 ;Overflow
|
|
LDA Value16+1
|
|
PHA
|
|
LDA Value16
|
|
JSR MUL2
|
|
BCS @ovflw1 ;Overflow
|
|
JSR MUL2
|
|
BCS @ovflw1 ;Overflow
|
|
ADC Value16
|
|
STA Value16
|
|
PLA
|
|
ADC Value16+1
|
|
STA Value16+1
|
|
BCS @ovflw3 ;Overflow
|
|
|
|
JSR ChrGot
|
|
SEC
|
|
SBC #'0'
|
|
CLC
|
|
ADC Value16
|
|
STA Value16
|
|
BCC @ovflw3
|
|
INC Value16+1
|
|
BEQ @ovflw2 ;Overflow
|
|
CLC
|
|
RTS
|
|
|
|
@ovflw1 PLA
|
|
@ovflw2 SEC
|
|
@ovflw3 RTS
|
|
|
|
MUL2 ASL Value16
|
|
ROL Value16+1
|
|
RTS
|
|
;=================================================
|
|
; Shift in the hex value into running value
|
|
; Input
|
|
; (A) = '0'-'9' or $3A-$3F
|
|
; Output
|
|
; (Value) = running hex value
|
|
;=================================================
|
|
|
|
ShiftHexDec
|
|
SEC
|
|
SBC #'0' ;$00-$0F
|
|
ASL A
|
|
ASL A
|
|
ASL A
|
|
ASL A
|
|
|
|
LDX #4
|
|
@rloop ASL A
|
|
ROL Value16
|
|
ROL Value16+1
|
|
DEX
|
|
BNE @rloop
|
|
RTS
|
|
;=================================================
|
|
; This rtn has 2 entry points
|
|
; Input
|
|
; cp = ptr into cmd line buffer
|
|
; Output
|
|
; Z=1 - char is space or cr
|
|
; (A) - char (converted to uppercase)
|
|
; ($3595)
|
|
;=================================================
|
|
|
|
ChrGet INY ;bump index first
|
|
ChrGot LDA (cp),Y
|
|
AND #$7F ;Strip msb of char
|
|
CMP #'a'
|
|
BCC @1 ;Don't convert to ucase
|
|
AND #$DF ;ucase
|
|
@1 CMP #SPACE
|
|
BEQ @ret
|
|
CMP #CR
|
|
@ret RTS
|
|
;=================================================
|
|
; Is char btwn '0'-'9'
|
|
; Input
|
|
; Output
|
|
; C=0 yes
|
|
;=================================================
|
|
|
|
IsCharDec
|
|
CMP #'9'+1
|
|
BCS NoGud
|
|
CMP #'0'
|
|
BCC NoGud
|
|
CLC
|
|
RTS
|
|
NoGud SEC
|
|
RTS
|
|
;=================================================
|
|
; Check for hexdec char '0'-'9' and 'A'-'F'
|
|
; If char is 'A'-'F', convert to a value
|
|
; btwn $3A-$3F and return with C=0
|
|
; Input
|
|
; Output
|
|
|
|
;=================================================
|
|
|
|
IsCharHex
|
|
CMP #'A'
|
|
BCC IsCharDec ;chk for numeric char
|
|
CMP #'F'
|
|
BCS NoGud
|
|
SBC #$06 ;Make it $3A-$3F
|
|
CLC
|
|
RTS
|
|
;=================================================
|
|
; Check for a keypress. If
|
|
; Ctrl-C - Abort of linking process
|
|
; spacebar - Pause
|
|
; ($35BF)
|
|
|
|
AbortPause
|
|
LDA KBD
|
|
BPL @ret
|
|
BIT KBDSTROBE ;turn off keypressed flag
|
|
CMP #CTRLC+$80
|
|
BNE @ckspc
|
|
|
|
LDY #$1C ;Abort err #
|
|
JSR DisplayMsg
|
|
LDY #$1C
|
|
JSR StoreMsg
|
|
JMP DoBreak
|
|
|
|
@ckspc CMP #SPACE+$80 ;Is space bar depressed?
|
|
BNE @ret
|
|
@wloop LDA KBD ;Yes
|
|
BPL @wloop ;Wait for any keypress
|
|
@ret RTS
|
|
;=================================================
|
|
; Output thru EdAsm Interpreter Print Error rtn
|
|
; Don't return to the caller
|
|
; Input
|
|
; (A) - error code
|
|
; ($35E2)
|
|
|
|
ErrHandler JSR PrintError
|
|
JMP DoBreak
|
|
;=================================================
|
|
DupCmdErr
|
|
LDY #$10
|
|
JMP GoShowMsg
|
|
;
|
|
OptionError
|
|
LDY #$0F
|
|
JMP GoShowMsg
|
|
|
|
CmdFileErr
|
|
LDY #$0E
|
|
JMP GoShowMsg
|
|
|
|
WrongOrder
|
|
LDY #$02
|
|
JMP GoShowMsg
|
|
|
|
UnknownCmdErr
|
|
LDY #$1B
|
|
JMP GoShowMsg
|
|
|
|
RLDESDErr
|
|
LDY #$11
|
|
JMP GoShowMsg
|
|
|
|
ExtrnErr
|
|
LDY #$17 ;>255 EXTRN's
|
|
JMP GoShowMsg
|
|
|
|
CmdSynErr
|
|
LDY #$01
|
|
|
|
; $360D
|
|
GoShowMsgZ
|
|
JMP GoShowMsg
|
|
|
|
GoShowMsg
|
|
JSR DisplayMsg
|
|
|
|
;=================================================
|
|
; All the above errors will come here
|
|
; Close all files. Check for a ctrl-B
|
|
; If so, exit to monitor else re-load EdAsm.ED
|
|
; & transfer control to the editor
|
|
; Input
|
|
; Output
|
|
; ($3613)
|
|
|
|
DoBreak
|
|
LDA CmdAdr ;last MLI call return address
|
|
PHA
|
|
LDA CmdAdr+1
|
|
PHA
|
|
|
|
LDA #$01
|
|
STA CloseAllRecP8
|
|
LDA #$00
|
|
STA CloseAllRecP8+C_REFNUM
|
|
JSR PRODOS8
|
|
DC.B $CC ;CLOSE
|
|
DC.W CloseAllRecP8
|
|
|
|
PLA
|
|
STA CmdAdr+1
|
|
PLA
|
|
STA CmdAdr ;last MLI call return address
|
|
|
|
BIT KBDSTROBE ;turn off keypressed flag
|
|
BIT RDROM2 ;Read ROM; no write
|
|
JSR RDKEY ;Input char with cursor
|
|
CMP #CTRLB+$80
|
|
BNE Abort
|
|
|
|
TSX
|
|
STX StackSave
|
|
LDX #$80
|
|
TXS
|
|
LDA ROMIN2 ;read ROM/write LCbank2 (RR)
|
|
LDA ROMIN2
|
|
JMP MON ;std monitor entry w/beep
|
|
|
|
Abort JSR SetupEditor ;Proceed to load & then
|
|
JMP USRADR ; xfer control to EdAsm.Ed
|
|
;=================================================
|
|
; Put everything back in order
|
|
; Input
|
|
; Output
|
|
; Currently EI's ctrl-Y vector points @ $B198
|
|
; If EXEC mode is on, the entry is modified to $B1AB
|
|
; which is EdAsm's Interpreter MainLoop.
|
|
; ($3655)
|
|
;=================================================
|
|
|
|
DoExit
|
|
LDA OpenCmdRecP8+C_OUTREF
|
|
JSR CloseAnyFile ;Close the command file
|
|
JSR SetupEditor ;Load file and setup its memmap
|
|
BIT ExecMode ;Was cmd file EXEC from Editor?
|
|
BMI @1 ;Yes
|
|
JMP USRADR ;Exit via ctl-Y vector
|
|
|
|
@1 CLC
|
|
LDA USRADR+1 ;Setup the ctl-Y vector
|
|
ADC #$13 ;$B1AB-$B198
|
|
STA JumpAdr+1 ;Self-modifying code
|
|
LDA USRADR+2
|
|
ADC #$00
|
|
STA JumpAdr+2
|
|
BIT ROMIN2 ;read ROM/write LCbank2 (RR)
|
|
BIT ROMIN2
|
|
LDX #$F8 ;Set H/W stack
|
|
TXS
|
|
JumpAdr
|
|
JMP USRADR ;After patching, no longer JMP via ctl-Y vector
|
|
;=================================================
|
|
; Load EDASM's Editor & set up its memory map
|
|
; Input
|
|
; Output
|
|
; ($3682)
|
|
;=================================================
|
|
|
|
SetupEditor
|
|
JSR LoadEditor ;Load EDASM.ED
|
|
LDA #%01111111 ;$7F: free pages $B0
|
|
STA MemoryMap+22 ;P8 memory MemoryMap
|
|
LDA #%10000001 ;$81: free pages $B9-$BE
|
|
STA MemoryMap+23
|
|
LDA TxtBgn ;No file in mem
|
|
STA TxtEnd
|
|
LDA TxtBgn+1
|
|
STA TxtEnd+1
|
|
RTS ;Location:$3697
|
|
|
|
;=================================================
|
|
; Phase 1 uses 2 bytes from this table. However, the
|
|
; locations accessed should be $3698 and $369A
|
|
; & not $3697 and $3699. The bytes should be
|
|
; addr hi of the EXTRN & ENTRY tables
|
|
; ($3698)
|
|
|
|
L3698 DC.B $71 ;ENTRY table must be < $7100
|
|
DC.B $00
|
|
DC.B $91 ;EXTRN table must be < $9100
|
|
|
|
BitsTab DC.B $80,$40,$20,$10,$08,$04,$02,$01
|
|
|
|
; Default filenames of workfiles
|
|
|
|
AUTOLNKS STR 'EDASM.AUTOLINK'
|
|
DC.B $00
|
|
|
|
TempESD STR 'EDASM.TEMPESD'
|
|
DC.B $00
|
|
|
|
TempRLDName STR 'EDASM.TEMPRLD'
|
|
DC.B $00
|
|
;=================================================
|
|
|
|
DirectivesTab
|
|
DC.B 'BIN '
|
|
DC.B 'REL '
|
|
DC.B 'SYS '
|
|
DC.B 'ORG '
|
|
DC.B 'OPT '
|
|
DC.B 'ALN '
|
|
DC.B $00 ;Marks end of table
|
|
;
|
|
; JMP table ($36EA)
|
|
;
|
|
CmdTabLo
|
|
DC.B CmdBIN-1 ;Lo
|
|
DC.B CmdREL-1
|
|
DC.B CmdSYS-1
|
|
DC.B CmdORG-1
|
|
DC.B CmdOptions-1
|
|
DC.B CmdALN-1
|
|
|
|
CmdTabHi
|
|
DC.B (CmdBIN-1)>>8 ;Hi
|
|
DC.B (CmdREL-1)>>8
|
|
DC.B (CmdSYS-1)>>8
|
|
DC.B (CmdORG-1)>>8
|
|
DC.B (CmdOptions-1)>>8
|
|
DC.B (CmdALN-1)>>8
|
|
;=================================================
|
|
; ($36F6)
|
|
OptionsTab
|
|
DC.B 'MESXNDP'
|
|
DC.B $00
|
|
|
|
LinkObjName STR 'EDASM.LINKOBJ' ;65-byte buffer for pathname
|
|
DS.B $33 ;51
|
|
|
|
LinkMapName STR 'EDASM.LINKMAP' ;65-byte buffer for pathname
|
|
DS.B $33 ;51
|
|
|
|
CmdLineBuf DCB.B 128,SPACE ;Command Line Buffers
|
|
|
|
Origin DC.W $A0B0 ;Set by cmd/AuxType of 1st SRC file
|
|
srcCodeLen DC.W $A0A0 ;len of code image of SRC file
|
|
NegSrcORG DC.W $A0CC ;2's complement of a SRC file's Origin
|
|
objCurrSize DC.W $A0BE ;Addr+1 of code image
|
|
RelAdr DC.W $A0FF ;Relocated Adr
|
|
|
|
; Work area for a 3-byte trailer of an ESD record.
|
|
; The layout of this work area is as follows:
|
|
; offset Meaning
|
|
; 0 DB symbol flag's byte
|
|
; If ENTRY-type symbol
|
|
; 1 DW offset from start of code image
|
|
; If EXTRN-type symbol
|
|
; 1 DB symbol number referred to by RLD record
|
|
; 2 DB 0
|
|
|
|
|
|
ESDWrkRec DS ESDRecord
|
|
; DC.B $A0
|
|
; DC.B $A0
|
|
; DC.B $FE
|
|
RLD_Flags DC.B $A0 ;RLD flag-byte
|
|
|
|
ModuleNbr DC.B $A0 ;source file count/Module Number
|
|
numSrcFiles DC.B $A0 ;Counter
|
|
TargetObjType DC.B $00 ;OBJECT filetype
|
|
|
|
; Table of ptrs to 1st EXTRN rec of each SRC file
|
|
; within the EXTRN table.
|
|
|
|
srcModTabLo DS.B 50
|
|
srcModTabHi DS.B 50
|
|
|
|
; Position counter of beginning of code image (ORG ADRS)
|
|
; within the OBJECT file for src file module #s 0-49
|
|
|
|
orgAdrLo DS.B 50
|
|
orgAdrHi DS.B 50
|
|
|
|
; Position counter of end of code image (END ADRS) within
|
|
; the OBJECT file for src file module #s 0-49
|
|
|
|
EndAddrLo DS.B 50
|
|
EndAddrHi DS.B 50
|
|
;=================================================
|
|
; General purpose pathname work area.
|
|
; Set this b4 opening a disk file.
|
|
; ($393D)
|
|
|
|
pathNameBuf DS.B 64 ;Should be 65!
|
|
|
|
MapDataBuf DCB.B 90,SPACE ;data buf for LINKMAP;
|
|
|
|
SYMLEN DC.B $A0 ;temp store for len of symbolicname
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Use to open source file(s) which are of type REL
|
|
|
|
OpenSrcRecP8
|
|
DC.B $03
|
|
DC.W pathNameBuf
|
|
DC.W srcIOAddr ;1024-byte buf for ProDOS
|
|
DC.B $00
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; ProDOS parameter blocks for Command File which
|
|
; is a TXT file. Each text line is terminated by a CR
|
|
|
|
OpenCmdRecP8
|
|
DC.B $03 ;count
|
|
DC.W pathNameBuf ;PathName
|
|
DC.W XA900 ;1024-byte buf required by P8
|
|
DC.B $00
|
|
|
|
ReadCmdRecP8
|
|
DC.B $04 ;count
|
|
DC.B $00
|
|
DC.W CmdLineBuf
|
|
DC.W 128 ;At most 128 chars/line
|
|
DC.W 0 ;# actual read (not referenced)
|
|
|
|
NewLineRecP8
|
|
DC.B $03 ;NEWLINE
|
|
DC.B $00
|
|
DC.B $7F ;AND mask=ignore msb i.e. both $0D/$8D are accepted
|
|
DC.B CR ;newline char
|
|
|
|
; ($39F0) Use to set file posn to beginning of Command File
|
|
|
|
MarkCmdRecP8
|
|
DC.B $02 ;SETMARK
|
|
DC.B $00
|
|
DS.B 3 ;This doesn't get changed
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; The P8 record below is used to destroy
|
|
; 1) old LINKMAP
|
|
; 2) old tempESD
|
|
; 3) old OBJECT file (if any)
|
|
; 4) old tempRLD
|
|
; pathNameBuf must be filled w/the filename before use.
|
|
|
|
DestroyRecP8
|
|
DC.B $01
|
|
DC.W pathNameBuf
|
|
|
|
CloseAnyRecP8
|
|
DC.B $01 ;Caller must set the RN
|
|
DC.B $00
|
|
|
|
CloseAllRecP8
|
|
DC.B $01 ;Use to close ALL open files
|
|
DC.B $00
|
|
|
|
; This record is not used
|
|
|
|
L39FC
|
|
DC.B $04 ;whats this?
|
|
DC.B $00
|
|
DC.B $00
|
|
DC.B $00
|
|
DC.B $00
|
|
DC.B $00
|
|
DC.B $00
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Used to get File Info of a source (REL) file
|
|
|
|
GetFileInfoRecP8
|
|
DC.B 10
|
|
DC.W pathNameBuf
|
|
DC.B 0
|
|
srcType DC.B 0
|
|
srcORG DC.W 0 ;auxtype
|
|
DC.B 0
|
|
DC.W 0
|
|
DC.W 0
|
|
DC.W 0
|
|
DC.W 0
|
|
DC.W 0
|
|
|
|
; Used to set the file position of a src file
|
|
|
|
MarkSrcRecP8
|
|
DC.B $02 ;SETMARK
|
|
DC.B $00
|
|
DS.B 3 ;Caller must set this
|
|
|
|
; Used to read the first 2 bytes of a SRC file
|
|
; which is the length of its code image
|
|
|
|
ReadCodeLenRecP8
|
|
DC.B $04
|
|
DC.B $00
|
|
DC.W srcCodeLen ;2-byte data buf
|
|
DC.W $0002 ;# of bytes to be read
|
|
DC.W $A080 ;actual # read (unused)
|
|
|
|
; ($3A22) For reading SRC, tempRLD, tempESD
|
|
; For appending to OBJECT file.
|
|
|
|
RWFileRecP8
|
|
DC.B $04
|
|
DC.B $00
|
|
DC.W srcDataBuf ;data buf
|
|
DC.W 0 ;Set this b4 calling PRODOS
|
|
DC.W 0 ;actual # of bytes read
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Use to open a 1) tempESD 2) OBJECT file
|
|
|
|
Open3RecP8
|
|
DC.B $03
|
|
DC.W pathNameBuf
|
|
DC.W X3F00 ;1024-byte buf for PRODOS
|
|
DC.B 0
|
|
|
|
; Use to write 1) TempESD 2) OBJECT files
|
|
|
|
Write3RecP8
|
|
DC.B $04
|
|
DC.B 0
|
|
DC.W X9100 ;Data Buf
|
|
DC.W $A0A0 ;write len
|
|
DC.W $B1A0 ;Actually written
|
|
|
|
; Read one page (256 bytes) of code image of current SRC file
|
|
|
|
ReadCodeRecP8
|
|
DC.B $04
|
|
DC.B 0
|
|
DC.W X9100 ;Data Buf
|
|
DC.W $0000
|
|
DC.W $A0D5
|
|
|
|
; Use to create BIN/REL/SYS OBJECT files
|
|
; Also use to create TempESD/TempRLD binary files
|
|
; The filetype & auxtype must be set first
|
|
|
|
CreateRecP8
|
|
DC.B 7
|
|
DC.W pathNameBuf
|
|
DC.B $E3 ;full access
|
|
DC.B $00 ;filetype
|
|
DC.W $0000 ;auxtype
|
|
DC.B $01 ;seedling
|
|
DC.W 0
|
|
DC.W 0
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; This P8 record is used to open
|
|
; 1) LINKMAP text file
|
|
; 2) tempRLD
|
|
|
|
Open2RecP8
|
|
DC.B $03
|
|
DC.W pathNameBuf
|
|
DC.W X4300 ;1024-byte buf
|
|
DC.B $00
|
|
|
|
; This P8 record is used to create LINKMAP file (which is a TXT file)
|
|
|
|
CreateMapRecP8
|
|
DC.B 7
|
|
DC.W pathNameBuf
|
|
DC.B $E3 ;full access
|
|
DC.B TXT_type
|
|
DC.W 0
|
|
DC.B $01 ;storage type=seedling
|
|
DC.W 0
|
|
DC.W 0
|
|
;=================================================
|
|
; Use to write the LINKMAP text file
|
|
; WrMapFIdx doubles as # of bytes to write
|
|
; besides being used as an index to store the
|
|
; chars into the Map File's Data Buf (MapDataBuf)
|
|
|
|
WriteMapRecP8
|
|
DC.B $04
|
|
DC.B $00
|
|
DC.W MapDataBuf ;data buf addr
|
|
MapIndex ;Doubles as # of bytes to write
|
|
DC.W $A0C3 ;at most 128 bytes (hi-byte=0)
|
|
DC.W $A080
|
|
;=================================================
|
|
; Use to
|
|
; 1) get eof of LINKMAP file, then
|
|
; 2) set the file posn to its EOF
|
|
|
|
EOFRecP8
|
|
DC.B $02 ;GET_EOF/SETMARK
|
|
DC.B $00
|
|
DS.B 3
|
|
|
|
; Use to write 1) TempRLD 2) TempESD files
|
|
|
|
WriteTmpRecP8
|
|
DC.B $04
|
|
DC.B $00
|
|
DC.W srcDataBuf ;source data buffer
|
|
DC.W 0 ;# of bytes to write
|
|
DC.W $A0A0
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Use to move the file position to the beginning
|
|
; 1) of the tempRLD file
|
|
; 2) OBJECT file
|
|
|
|
SMarkBOFRecP8
|
|
DC.B $02
|
|
DC.B $00
|
|
DS.B 3 ;Not changed
|
|
;=================================================
|
|
; Message pointers sub-tables
|
|
; ($3A78)
|
|
|
|
MsgTabLo
|
|
DC.B L3ADE
|
|
DC.B L3B02
|
|
DC.B L3B1F
|
|
DC.B L3BB7
|
|
DC.B L3BDD
|
|
DC.B L3BFF
|
|
DC.B L3C1E
|
|
DC.B L3C3F
|
|
DC.B L3C63
|
|
DC.B L3C83
|
|
DC.B L3CA0
|
|
DC.B L3CB7
|
|
DC.B L3CCF
|
|
DC.B L3CEB
|
|
DC.B L3B55
|
|
DC.B L3B7B
|
|
DC.B L3BA0
|
|
DC.B L3D06
|
|
DC.B L3D22
|
|
DC.B L3D3F
|
|
DC.B L3D4B
|
|
DC.B L3D58
|
|
DC.B L3D8D
|
|
DC.B L3D9A
|
|
DC.B L3DBE
|
|
DC.B L3DD6
|
|
DC.B L3DEE
|
|
DC.B L3B3A
|
|
DC.B L3AB4
|
|
DC.B L3D75
|
|
|
|
MsgTabHi
|
|
DC.B L3ADE>>8 ;0
|
|
DC.B L3B02>>8 ;1
|
|
DC.B L3B1F>>8 ;2
|
|
DC.B L3BB7>>8 ;3
|
|
DC.B L3BDD>>8 ;4
|
|
DC.B L3BFF>>8 ;5
|
|
DC.B L3C1E>>8 ;6
|
|
DC.B L3C3F>>8 ;7
|
|
DC.B L3C63>>8 ;8
|
|
DC.B L3C83>>8 ;9
|
|
DC.B L3CA0>>8 ;10
|
|
DC.B L3CB7>>8 ;11
|
|
DC.B L3CCF>>8 ;12
|
|
DC.B L3CEB>>8 ;13
|
|
DC.B L3B55>>8 ;14
|
|
DC.B L3B7B>>8 ;15
|
|
DC.B L3BA0>>8 ;16
|
|
DC.B L3D06>>8 ;17
|
|
DC.B L3D22>>8 ;18
|
|
DC.B L3D3F>>8 ;19
|
|
DC.B L3D4B>>8 ;20
|
|
DC.B L3D58>>8 ;21
|
|
DC.B L3D8D>>8 ;22
|
|
DC.B L3D9A>>8 ;23
|
|
DC.B L3DBE>>8 ;24
|
|
DC.B L3DD6>>8 ;25
|
|
DC.B L3DEE>>8 ;26
|
|
DC.B L3B3A>>8 ;27
|
|
DC.B L3AB4>>8 ;28
|
|
DC.B L3D75>>8 ;29
|
|
|
|
; Messages starts here
|
|
|
|
L3AB4 DC.B 'LINKER ABORTED'
|
|
DC.B CR
|
|
DC.B 'PRESS RETURN TO CONTINUE\'
|
|
DC.B CR
|
|
DC.B '\'
|
|
L3ADE DC.B 'ProDOS Linker 1.0'
|
|
DC.B CR,CR
|
|
DC.B 'Command Filename'
|
|
DC.B '\' ;end of msg
|
|
L3B02 DC.B 'ERR: Syntax error in command'
|
|
DC.B '\'
|
|
L3B1F DC.B 'ERR: Invalid Command order'
|
|
DC.B '\'
|
|
L3B3A DC.B 'ERR: Unknown command found'
|
|
DC.B '\'
|
|
L3B55 DC.B 'ERR: Empty or incomplete command'
|
|
DC.B ' file'
|
|
DC.B '\'
|
|
L3B7B DC.B 'ERR: Invalid option or option syntax'
|
|
DC.B '\'
|
|
L3BA0 DC.B 'ERR: Duplicate command'
|
|
DC.B '\'
|
|
L3BB7 DC.B 'Phase 0 : Commands & Options Selected'
|
|
DC.B '\'
|
|
L3BDD DC.B 'Phase 1 : Building DEF/REF tables'
|
|
DC.B '\'
|
|
L3BFF DC.B 'Phase 2 : Resolving REF-EXTRNs'
|
|
DC.B '\'
|
|
L3C1E DC.B 'Phase 3 : Relocating Object code'
|
|
DC.B '\'
|
|
L3C3F DC.B 'Phase 4 : Generating Object RLD-ESD'
|
|
DC.B '\'
|
|
L3C63 DC.B 'Phase 5 : Sorting loadmap index'
|
|
DC.B '\'
|
|
L3C83 DC.B 'Phase 6 : Generating loadmap'
|
|
DC.B '\'
|
|
L3CA0 DC.B 'ERR: Symbol table full'
|
|
DC.B '\'
|
|
L3CB7 DC.B 'ERR: Too many REL files'
|
|
DC.B '\'
|
|
L3CCF DC.B 'ERR: File is not a REL file'
|
|
DC.B '\'
|
|
L3CEB DC.B 'ERR: REL file is too large'
|
|
DC.B '\'
|
|
L3D06 DC.B 'ERR: REL file ESD too large'
|
|
DC.B '\'
|
|
L3D22 DC.B 'Duplicate DEF-ENTRY symbol, '
|
|
DC.B '\'
|
|
L3D3F DC.B 'of module #'
|
|
DC.B '\'
|
|
L3D4B DC.B ' in module #'
|
|
DC.B '\'
|
|
L3D58 DC.B 'Undefined REF-EXTRN symbol, '
|
|
DC.B '\'
|
|
L3D75 DC.B 'REF-DEF SIZE mismatch, '
|
|
DC.B '\'
|
|
L3D8D DC.B 'UNREFERENCED'
|
|
DC.B '\'
|
|
L3D9A DC.B 'ERR: >255 EXTRN''s in REL output ESD'
|
|
DC.B '\'
|
|
L3DBE DC.B 'MOD ORG END MODULE'
|
|
DC.B CR
|
|
DC.B '\'
|
|
L3DD6 DC.B ' # ADRS ADRS NAME '
|
|
DC.B CR
|
|
DC.B '\'
|
|
L3DEE DC.B ' ADRS M# SYMBOL MODULE'
|
|
DC.B ' X-REF LIST '
|
|
DC.B ' PAGE '
|
|
DC.B '\'
|
|
DC.B '14-MAR-84'
|
|
DC.B '23:42 '
|
|
|
|
ENDP
|
|
END
|