From dea81473b5c2088289221b03b23d9ced8950d7ca Mon Sep 17 00:00:00 2001 From: markpmlim Date: Sat, 19 Mar 2016 15:29:24 +0800 Subject: [PATCH] Add MPW Asm port of EdAsm Linker --- EDASM.SRC/LINKER/equates.aii | 1 + EDASM.SRC/LINKER/linker.aii | 1 + 2 files changed, 2 insertions(+) create mode 100644 EDASM.SRC/LINKER/equates.aii create mode 100644 EDASM.SRC/LINKER/linker.aii diff --git a/EDASM.SRC/LINKER/equates.aii b/EDASM.SRC/LINKER/equates.aii new file mode 100644 index 0000000..75a2135 --- /dev/null +++ b/EDASM.SRC/LINKER/equates.aii @@ -0,0 +1 @@ +; This EdAsm/Asm816 source code file was converted to AsmIIGS ; by EdAsmCvtIIGS version 1.2 on 4/4/12 at 7:22:43 AM ; EXPORT TXT_type ; EXPORT X4300 ; EXPORT X3F00 ; EXPORT CR ; EXPORT srcIOAddr ; EXPORT SPACE ; EXPORT TxtEnd ; EXPORT ExecMode ; EXPORT USRADR ; EXPORT ROMIN2 ; EXPORT StackSave ; EXPORT RDKEY ; EXPORT CmdAdr ; EXPORT COUT ; EXPORT CROUT ; EXPORT GETLN ; EXPORT XA900 ; EXPORT MON ; EXPORT PRERR ; EXPORT HOME ; EXPORT SETVID ; EXPORT SETKBD ; EXPORT RDROM2 ; EXPORT TxtBgn ; EXPORT LoadAdrEditor ; EXPORT KBDSTROBE ; EXPORT KBD ; EXPORT EdAsmDir ; EXPORT cp ; EXPORT ENTRPI ; EXPORT ENTRPJ ; EXPORT I.TH ; EXPORT J.TH ; EXPORT III ; EXPORT JJJ ; EXPORT StartIndex ; EXPORT EndIndex ; EXPORT Jump ; EXPORT NUMRECS ; EXPORT X9200 ; EXPORT UpperBound ; EXPORT LowerBound ; EXPORT Z96 ; EXPORT msgP ; EXPORT Z8E ; EXPORT Z86 ; EXPORT X9100 ; EXPORT C.FILEID ; EXPORT C.AUXID ; EXPORT xtrnNbr ; EXPORT XA8E0 ; EXPORT Z88 ; EXPORT Z9E ; EXPORT C.REQCNT ; EXPORT C.DATABUF ; EXPORT Z82 ; EXPORT Z80 ; EXPORT C.TRANSCNT ; EXPORT SRCDBUF ; EXPORT SRCP ; EXPORT C.MARK ; EXPORT CurrORG ; EXPORT symP ; EXPORT symbolTab ; EXPORT xtrnRecP ; EXPORT xternTab ; EXPORT entRecP ; EXPORT EntryTab ; EXPORT OptFlagsTab ; EXPORT SWITCH ; EXPORT Value16 ; EXPORT C.REFNUM ; EXPORT C.OUTREF ; EXPORT InBuf ; EXPORT PROMPT ; EXPORT PRTERROR ; EXPORT PRODOS8 ; EXPORT PageCnt ; EXPORT LineCnt ; EXPORT IsNumSort ; EXPORT WhichType ; EXPORT IsOptions ; EXPORT Option_D ; EXPORT PageOption ; EXPORT EREFF ; EXPORT XRefOption ; EXPORT SORTLMF ; EXPORT MapOption ; EXPORT MemoryMap ; EXPORT IVERSION ; EXPORT MINIVERS ; EXPORT STACK ; EXPORT SaveA ; CHR ";" ;================================================= ; Equates used by EdAsm's modules ; ; ASCII keycodes ; CTRLA EQU $01 CTRLB EQU $02 CTRLC EQU $03 CTRLD EQU $04 CTRLE EQU $05 CTRLF EQU $06 BEL EQU $07 BS EQU $08 TAB EQU $09 FF EQU $0C CR EQU $0D CTRLN EQU $0E CTRLO EQU $0F CTRLQ EQU $11 CTRLR EQU $12 CTRLS EQU $13 CTRLT EQU $14 CTRLU EQU $15 CTRLV EQU $16 CTRLW EQU $17 CTRLX EQU $18 ;cancel ESCAPE EQU $1B SPACE EQU $20 UNDERSCORE EQU $5F DEL EQU $7F ;================================================= ; filetypes recognised by the various EdAsm modules TXT_type EQU $04 BIN_type EQU $06 DIR_type EQU $0D REL_type EQU $FE SYS_type EQU $FF ;================================================= ; Apple ][ Standard Zero page WNDWDTH EQU $21 CH EQU $24 CV EQU $25 BASL EQU $28 INVFLG EQU $32 PROMPT EQU $33 CSWL EQU $36 ;Output hook KSWL EQU $38 ;Input hook A1 EQU $3C A2 EQU $3E A4 EQU $42 ;================================================= ; These zpage locations are referenced by 2 or ; more of EdAsm's modules LOMEM EQU $0A ;=$0801 TxtBgn EQU $0A ;Reg5 of Sweet16 TxtEnd EQU $0E ;Reg7 HIMEM EQU $0C ;=$9900 Not used by EDASM.ASM StackSave EQU $49 ;Save area for H/W stack ptr VIDEOSLT EQU $50 ;=$Cs where s=1-3 (if 80-col video card present) FileType EQU $51 ;filetype ExecMode EQU $53 ;Exec mode PrtrMode EQU $54 ;=$80,$00 - Printer ON/OFF TABchar EQU $5F ;Set by Editor PrintColumn EQU $61 ;curr print col UserTABTbl EQU $68 ;$68-$71 User defined TAB table PrintFlag EQU $73 ;-1=Print Cmd, 0=List Cmd STACKP2 EQU $73 ;Save area for H/W stack ptr on fatal err SwapMode EQU $74 ;Split-buf mode 0-normal,1=buf1,2=buf2 CaseMode EQU $75 ;ucase/lcase CmdDelim EQU $78 ;Cmd Delimiter/Separator TruncFlag EQU $79 ;=$FF-truncate comments ;================================================= X2000 EQU $2000 ;Load & Exec addr of SYS Files LoadAdrEditor EQU $8900 ;Load Addr of Editor Module ;================================================= ; 1024-byte I/O buffers for ProDOS8 XA900 EQU $A900 XAD00 EQU $AD00 ;================================================= ; EdAsm Global Page ; Used to pass parameters btwn EdAsm's ; modules viz Editor, Assembly & Linker ; The EI must be resident all the times ; EdAsm Interpreter's Global Page ; Used to pass parameters btwn EdAsm's ; modules viz Editor, Assembly & Linker ; The EI must be resident all the times XBD00 EQU $BD00 ;General Purpose 128-byte buffers XBD80 EQU $BD80 ; used by EdAsm's modules XBE00 EQU $BE00 ;$BE00-$BE3F (curr Pathname) DEVCTLS EQU $BE40 ;($BE40-$BE61) Init to $C3 if 80-col card present TABTable EQU $BE60 ;$BE60-$BE62 DATETIME EQU $BE64 ;$BE64-$73 EdAsmDir EQU $BE79 ;Where EDASM is stored on disk PrintError EQU $BEFC ;EdAsm Interpreter error message rtn ;================================================= ; Apple ][ STACK EQU $0100 ;6502 H/W stack InBuf EQU $0200 TxBuf2 EQU $0280 SOFTEV EQU $03F2 ;RESET vector PWREDUP EQU $03F4 ;Power up byte USRADR EQU $03F8 ;ctrl-Y vector ;================================================= ; Some ProDOS 8 Global Page loctions referenced ; by EdAsm's modules PRODOS8 EQU $BF00 ;MLI entry point LASTDEV EQU $BF30 MemoryMap EQU $BF58 ;Memory bit map P8DATE EQU $BF90 P8TIME EQU $BF92 MACHID EQU $BF98 SLTBYT EQU $BF99 ;Slot ROM map CmdAdr EQU $BF9C ;last MLI call return address MINIVERS EQU $BFFC ;minimum interpreter version IVERSION EQU $BFFD ;interpreter version ;================================================= ; Apple ][ Soft Switches KBD EQU $C000 CLR80VID EQU $C00C KBDSTROBE EQU $C010 BUTN3 EQU $C060 BUTN2 EQU $C063 RDBANK2 EQU $C080 ;Read only RAM bank 2; no write ROMIN2 EQU $C081 ;Read ROM/Write RAM bank 2 (RR) RDROM2 EQU $C082 ;Read ROM; no write LCBANK2 EQU $C083 ;Read/Write RAM bank 2 (RR) BASICINT EQU $C300 XC30B EQU $C30B ;card identification XC30C EQU $C30C XD000 EQU $D000 ;LC Bank2 - SW16 or Asm's Print Symbol Table BASCLD EQU $E000 ;AppleSoft ColdStart ;================================================= ; Apple ][ Monitor Entry Points SWEET16 EQU $F689 ;Original IntegerBASIC ROM entry point PRNTAX EQU $F941 PRBLNK EQU $F948 INIT EQU $FB2F BELL1 EQU $FBDD VTABZ EQU $FC24 HOME EQU $FC58 CLREOL EQU $FC9C WAIT EQU $FCA8 RDKEY EQU $FD0C RDCHAR EQU $FD35 GETLN EQU $FD6A ;input line w/prompt CROUT EQU $FD8E ;issue carriage return COUT EQU $FDED ;output char via user's I/O COUT1 EQU $FDF0 ;output via video screen MOVE EQU $FE2C SETNORM EQU $FE84 SETKBD EQU $FE89 SETVID EQU $FE93 PRERR EQU $FF2D MON EQU $FF65 MONZ EQU $FF69 IRQV EQU $FFFE ;================================================= ; SW16 registers when using 6502 instructions REG0 EQU $00 ;Doubles as the Accumulator REG1 EQU $02 REG2 EQU $04 REG3 EQU $06 REG4 EQU $08 REG5 EQU $0A ;Points @ 1st char of curr edited file REG6 EQU $0C ;HiMem of EdAsm REG7 EQU $0E ;Points @ last char of curr edited file REG8 EQU $10 REG9 EQU $12 REG10 EQU $14 REG11 EQU $16 REG12 EQU $18 ;Subroutine return stack pointer REG13 EQU $1A ;Result of a comparison instruction REG14 EQU $1C ;Status Register REG15 EQU $1E ;Program Counter ;================================================= ; Sweet16 registers ; These labels are for the EdAsm assembler ; For Merlin8, Rn are pre-defined and ; do not need to be declared. R0 EQU 0 R1 EQU 1 R2 EQU 2 R3 EQU 3 R4 EQU 4 R5 EQU 5 R6 EQU 6 R7 EQU 7 R8 EQU 8 R9 EQU 9 R10 EQU 10 R11 EQU 11 R12 EQU 12 ;Subroutine return stack pointer R13 EQU 13 ;Result of a comparison instruction R14 EQU 14 ;Status Register R15 EQU 15 ;Program Counter ;================================================= ; Lifted from ProDOS v1.7 ; xdos parameters: C_PCNT EQU $0 ; (count) C_DEVNUM EQU $1 ; (value) C_REFNUM EQU $1 ; (value) C_INTNUM EQU $1 ; (value) C_PATH EQU $1 ;&2 (pointer) C_ISNEWL EQU $2 ; (mask) C_DATABUF EQU $2 ;&3 (value) C_BUFADR EQU $2 ;&3 (address) C_INTADR EQU $2 ;&3 (address) C_MARK EQU $2 ;->4 (value) C_EOF EQU $2 ;->4 (value) C_ATTR EQU $3 ; (flags) C_NEWL EQU $3 ; (character) C_BUFPTR EQU $3 ;&4 (pointer) C_NEWPATH EQU $3 ;&4 (pointer) C_FILEID EQU $4 ; (value) C_REQCNT EQU $4 ;&5 (value) C_BLKNUM EQU $4 ;&5 (address) C_OUTREF EQU $5 C_AUXID EQU $5 ;&6 (value) C_TRANSCNT EQU $6 ;&7 (value) C_FKIND EQU $7 ; (value) C_DATE EQU $8 ;&9 (value) C_OUTBLK EQU $8 ;&9 (count) C_TIME EQU $A ;&b (value) C_MODDATE EQU $A ;&b (value) C_MODTIME EQU $C ;&d (value) C_CREDATE EQU $E ;&f (value) C_CRETIME EQU $10 ;&11 (value) ;================================================= ; Equates specific to EdAsm's Linker Module ;================================================= ; Zero page usage by Linker Z80 EQU $80 Z82 EQU $82 srcP EQU $84 ;ptr into SRC file data buf Z86 EQU $86 ;ptr into tempESD buf ($9100) Z88 EQU $88 ;General purpose rec ptr entRecP EQU $8A ;ptr into DEF/ENTRY table 24-byte records xtrnRecP EQU $8C ;ptr into REF/EXTRN table 8-byte records symP EQU $8E ;ptr into $9200-$A8DF 16-byte records (SymbolicName table) Z8E EQU $8E ;re-cycled cp EQU $90 ;ptr into cmd line buf msgP EQU $92 CurrORG EQU $94 ;Starting PC of curr src file objCodeLen EQU $96 ;or Curr EOF of REL OBJ file LowerBound EQU $98 ;old offset into curr code image UpperBound EQU $9A ;curr offset into curr code (why is $9B not used?) SaveA EQU $9C ; image in memory Z9E EQU $9E ;Flag if a src PN is preceded by an ; xtrnNbr EQU $9F ;# of EXTRNs in REL OBJ file's ESD WhichType EQU $A0 ;filetype of target obj file BIN=$01,REL=$80,SYS=$02 IsOptions EQU $A1 ;TRUE when the OPTION cmd is encountered OptFlagsTab EQU $A2 ;Table of current option flags MapOption EQU $A2 ;default ON EntryRefOption EQU $A3 ;default ON SortOption EQU $A4 ;default ON XRefOption EQU $A5 ;default ON IsNumSort EQU $A6 ;default OFF Option_D EQU $A7 ;default OFF PageOption EQU $A8 ;default OFF ; Use to help set flags $A2-$A8 ; as well as return as a 16-bit value SWITCH EQU $AB ;ON/OFF ($80/$00) Value16 EQU $AB ;Value of arithmetic/numeric expression LineCnt EQU $AD PageCnt EQU $AE JJJ EQU $AF ;use during an internal sort III EQU $B1 StartIndex EQU $B3 EndIndex EQU $B5 Jump EQU $B7 NUMRECS EQU $B9 ;Total # of records in ENTRY table J_TH EQU $BB I_TH EQU $BD ENTRPJ EQU $BF ENTRPI EQU $C1 ;================================================= ; Memory map by Linker srcIOAddr EQU $0800 ;1024-byte buf for REL src file(s) ($0800-$0BFF) srcDataBuf EQU $0C00 ;R/W data buf for file(s) ($0C00-$1FFF) X3F00 EQU $3F00 ;1024-byte buf for OBJ/tempESD files ($3F00-$42FF) X4300 EQU $4300 ;1024-byte buf for LINKMAP/tempRLD file ($4300-$46FF) EntryTab EQU $4700 ;DEFine table (24-byte records) ($4700-$70FF) xternTab EQU $7100 ;REFerence table (8-byte records) ($7100-$90FF) X9100 EQU $9100 ;databuf-tempESD/REL Obj file ($9100-$91FF) X9200 EQU $9200 ;1 mem page data buf for code image read symbolTab EQU $9200 ;Symbol table (16-byte records) ($9200-$A8DF?) XA8E0 EQU $A8E0 ;Upper limit of Symbol table currPfxBuf EQU $BB80 ;Curr Prefix set by user in Editor's environment ;================================================= ; There are flags which describes the characteristics ; of a symbol - ref pg 231 undefined EQU $80 unreferenced EQU $40 relative EQU $20 external EQU $10 entry EQU $08 macro EQU $04 nosuchlabel EQU $02 fwdreferenced EQU $01 maxSrcFiles EQU 50 ;max # of SRC file that can be linked NULL EQU 0 Str15 RECORD 0 elements DS.B 16 sizeof EQU * ;16 bytes ENDR ; ENTRY Record EntryRecord RECORD 0 symbolName DS Str15 ;offset: 0 p-String up to 16 chars including len byte fileNum DS.B 1 ;offset: 16 file # of src file (start fr 0) flags DS.B 1 ;offset: 17 symbol-type relAddr DS.W 1 ;offset: 18 relocated addr head DS.W 1 ;offset: 20 Ptr to EXTRN record tail DS.W 1 ;offset: 22 Ptr to EXTRN record sizeof EQU * ;24 bytes ENDR ; EXTRN record XtrnRecord RECORD 0 next EQU * symNamePtr DS.W 1 ;offset: 0 ptr to a record in SymbolicName table ($9200) entryPtr DS.W 1 ;offset: 2 Ptr to an ENTRY record; NULL initially fileNum DS.B 1 ;offset: 4 file # of src file (also called module #) flags DS.B 1 ;offset: 5 flagByte symbolNum DS.B 1 ;offset: 6 symbol # referred to by an RLD record externNum DS.B 1 ;offset: 7 extern number (< 255) sizeof EQU * ;8 bytes ENDR ; Symbolic Name Record SymbolRecord RECORD 0 externNum EQU * symbolName DS Str15 ;p-String up to 16 chars including len byte sizeof EQU * ;16 bytes ENDR ; Relocation Dictionary record - variant record RLDRecord RECORD 0 flags DS.B 1 ;offset: 0 flagByte codeOffset DS.W 1 ;offset: 1 field offset in code esdNum EQU * low8bits DS.B 1 ;offset: 3 sizeof EQU * ;4 bytes ENDR ; External Symbol Directory Record - mini record after ; an external symbolic name - variant record ESDRecord RECORD 0 flags DS.B 1 ;offset: 0 flagByte relAddr EQU * ;If symbol is ENTRY-type externNum DS.B 1 ;offset: 1 if symbol is EXTRN-type unused DS.B 1 ;offset: 2 sizeof EQU * ;3 bytes ENDR LoadMapRecord RECORD 0 entryPtr DS.W 1 ;offset: 0 ptr to an ENTRY record relAddr DS.W 1 ;offset: 2 relocated address sizeof EQU * ;4 bytes ENDR \ No newline at end of file diff --git a/EDASM.SRC/LINKER/linker.aii b/EDASM.SRC/LINKER/linker.aii new file mode 100644 index 0000000..05e89d1 --- /dev/null +++ b/EDASM.SRC/LINKER/linker.aii @@ -0,0 +1 @@ +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+1 LDA #xternTab STA xtrnRecP+1 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 ADC RWFileRecP8+C_TRANSCNT+1 ; (or EO file data buf + 1=$2000) STA Z80+1 ;END 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 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 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 # 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+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 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+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 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+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+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+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+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 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 STA entRecP+1 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+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 ;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+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+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+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+1 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+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+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 \ No newline at end of file