home *** CD-ROM | disk | FTP | other *** search
-
- /**************************************************************************
- *
- * lOADER FOR 6502 RELOCATABLE BINARY FORMAT
- *
- * tHE LOADER SUPPORTS 16 BIT O65 VERSION 1 FILES WITHOUT UNDEFINED
- * REFERENCES. aLSO IT DOESN'T LIKE PAGEWISE RELOCATION AND 65816
- * CODE, BECAUSE THERE ARE DIFFERENT/ADDITIONAL RELOCATION ENTRIES.
- *
- * tHE SUPPORT ROUTINES, THAT HAVE TO BE CHANGED ARE AT THE END OF THE
- * FILE. tHE STUFF IN THIS FILE IS IN ABSOLUTE FORMAT (WELL, YOU HAVE TO
- * BOOTSTRAP FROM SOMETHING :-)
- * tHE SUPPORT ROUTINES FOR THE FILE HANDLING ARE FOR THE OPERATING SYSTEM
- * os/a65, AS OF VERSION 1.3.10B. tHE FIRST PART OF THE FILE (WRAPPED IN
- * "#IFDEF c64") SHOWS HOW TO USE IT WITH A c64, FOR EXAMPLE.
- *
- * tHE SUBROUTINE 'LOADER' IS CALLED WITH A FILE DESCRIPTOR, THAT HAS A
- * MEANING FOR THE SUPPORT ROUTINES, IN THE x REGISTER.
- * tHE FILE MUST ALREADY BE OPEN. aLSO BINIT MUST HAVE BEEN CALLED BEFORE.
- * tHE LOADER DOESN'T CLOSE THE FILE.
- *
- * sUPPORT ROUTINES ARE:
- * BINITA = HI BYTE START ADDRESS MEMORY TO HANDLE,
- *X = HI BYTE LENGTH OF MEMORY TO HANDLE
- * BALLOCA/Y = LENGTH OF BLOCK -> X = MEMORY DESCRIPTOR
- * BFREE X = MEMORY BLOCK DESCRIPTOR TO FREE
- * GETBADRX = MEMORY DESCRIPTOR -> A/Y ADDRESS OF MEMORY BLOCK
- *
- * ZALLOCA = LENGTH OF NEEDED ZEROPAGE BLOCK. RETURNS A=ADDRESS
- * ZFREEA = ADDRESS OF BLOCK TO FREE
- *
- * FGETCX = FILE DESCRIPTOR, RETURNS READ BYTE (C=0) OR ERROR (C=1)
- * tHE ERROR IS PASSED THROUGH; FGETC BLOCKS IF NO DATA
- * AVAILABLE
- * FGETBX = FILEDESCRIPTOR, A/Y = ADDRESS OF BLOCK DESCRIPTOR,
- * I.E. A WORD START ADDRESS AND A WORD LENGTH OF BLOCK.
- * RETURNS (C=0) OR ERROR IN ACCU (C=1).
- *
- **************************************************************************/
-
- /**************************************************************************
- * tHIS PART IS A BINDING FOR A c64
- * TO SHOW HOW IT WORKS
- */
-
- #DEFINEc64
-
- #IFDEF c64
-
- SYSMEM=$033C
- SYSZP=$57
-
-
- .WORD $0801
- *=$801
- .WORD NEXTL
- .WORD 10
- .BYT $9E, "2080",0
- NEXTL.WORD 0
- .DSB 2080-*, 0
-
- C64LOAD.(
- LDA #>prgend+255
- LDX #>$a000-prgend
- JSR BINIT; INIT MEMORY HANDLING
-
- LDA #7
- LDX #<FNAME
- LDY #>FNAME
- JSR $FFBD; SETFNPAR
-
- LDA #2
- LDX #11
- LDY #0
- JSR $FFBA; SETFPAR
-
- JSR $FFC0; OPEN
- BCS END
-
- LDX #2
- JSR $FFC6; CHKIN
- BCS END
-
- JSR LOADER; DON'T CARE ABOUT X, CHKIN DID IT
-
- PHP
- PHA
- JSR $FFCC; CLRCH
- LDA #2
- JSR $FFC3; CLOSE
- PLA
- PLP
- ENDRTS
-
- FNAME;.ASC "EXAMPLE",0
- .BYT $45, $58, $41, $4D, $50, $4C, $45, 0
- .)
-
- FGETC.(
- JSR $FFCF
- PHP
- PHA
- BCC CARRY
- LDA #"c"
- JSR $FFD2
- PLA
- PHA
- CARRY
- JSR HEXOUT
- LDA #$20
- JSR $FFD2
- PLA
- PLP
- RTS
- .)
-
- HEXOUT.(
- PHA
- LSR
- LSR
- LSR
- LSR
- JSR NIBOUT
- PLA
- NIBOUTAND #$0F
- CLC
- ADC #$30
- CMP #$3A
- BCC OK
- ADC #$41-$3A-1
- OKJMP $FFD2
- .)
-
- ZALLOC.(
- CMP #$80; SAVE FROM $90 UPWARD = os, BELOW IS ONLY BASIC
- BCS END
- LDA #$10
- ENDRTS
- .)
-
- ZFREE.(
- CLC
- RTS
- .)
-
- #ENDIF
-
- /**************************************************************************
- * hERE IS THE REAL LOADER CODE
- */
-
- #INCLUDE "FILE.DEF"
-
- #DEFINEe_nomem<-40
- #DEFINEe_fversion<-41
-
- LOADER .(
- P1=SYSZP
- P2=SYSZP+2
- -SYSZP+=4
-
- TMP=SYSMEM
- FILE=SYSMEM+1
- -SYSMEM+=2
- HEADER=SYSMEM
- -SYSMEM+=hdr_len
- TEXTB=SYSMEM; MEMORY BLOCK id
- TEXTA=SYSMEM+1; ADDRESS OF BLOCK
- TEXTL=SYSMEM+3; ADDRESS OF BLOCK
- TEXTD=SYSMEM+5; DIFFERENCE TO ASSEMBLE ADDRESS
- -SYSMEM+=7
- DATAB=SYSMEM
- DATAA=SYSMEM+1
- DATAL=SYSMEM+3
- DATAD=SYSMEM+5
- -SYSMEM+=7
- BSSB=SYSMEM
- BSSA=SYSMEM+1
- BSSD=SYSMEM+3
- -SYSMEM+=5
- ZEROA=SYSMEM
- ZEROD=SYSMEM+1
- -SYSMEM+=3
-
- STX FILE
- JSR FGETC
- BCS END
- STA TMP
- JSR FGETC
- BCS END
- TAY
- LDA TMP
- CPY #0
- BNE RT
- CMP #1
- BEQ LOAD
- RT LDA #e_fversion; OK, BUT NOT THIS VERSION
- ENDSEC
- RTS
-
- LOAD.(
- LDA #<HEADER
- STA P1
- LDA #>HEADER
- STA P1+1
- LDA #<hdr_len
- STA P1+2
- LDA #>hdr_len
- STA P1+3
-
- LDX FILE
- LDA #<P1
- LDY #>P1
- JSR FGETB
- BCS END
-
- ; HEADER LOADED, CHECK MAGIC AND VERSION
- LDA HEADER+hdr_magic
- CMP #$6F
- BNE END
- LDA HEADER+hdr_magic+1
- CMP #"6"
- BNE END
- LDA HEADER+hdr_magic+2
- CMP #"5"
- BNE END
- LDA HEADER+hdr_version
- CMP #0
- BNE END
- LDA HEADER+hdr_mode+1
- AND #%11110000
- BNE END
- ; NOW ALLOCATE BUFFERS
- LDA HEADER+hdr_tlen
- LDY HEADER+hdr_tlen+1
- STA TEXTL
- STY TEXTL+1
- JSR BALLOC
- STX TEXTB
- BCS NO_TEXT2
- JSR GETBADR
- STA TEXTA
- STY TEXTA+1
- SEC
- SBC HEADER+hdr_tbase
- STA TEXTD
- TYA
- SBC HEADER+hdr_tbase+1
- STA TEXTD+1
-
- LDA HEADER+hdr_dlen
- LDY HEADER+hdr_dlen+1
- STA DATAL
- STY DATAL+1
- JSR BALLOC
- STX DATAB
- BCS NO_DATA2
- NO_TEXT2 BCS NO_TEXT1
- JSR GETBADR
- STA DATAA
- STY DATAA+1
- SEC
- SBC HEADER+hdr_dbase
- STA DATAD
- TYA
- SBC HEADER+hdr_dbase+1
- STA DATAD+1
-
- LDA HEADER+hdr_blen
- LDY HEADER+hdr_blen+1
- JSR BALLOC
- STX BSSB
- BCS NO_BSS
- NO_TEXT1 BCS NO_TEXT
- NO_DATA2 BCS NO_DATA
- JSR GETBADR
- STA BSSA
- STY BSSA+1
- SEC
- SBC HEADER+hdr_bbase
- STA BSSD
- TYA
- SBC HEADER+hdr_bbase+1
- STA BSSD+1
-
- LDA HEADER+hdr_zlen
- JSR ZALLOC
- BCS NO_ZERO
- STA ZEROA
- SEC
- SBC HEADER+hdr_zbase
- STA ZEROD
- LDA #0
- STA ZEROD+1
-
- JMP DO_LOAD
-
- &NO_FILE LDA ZEROA
- JSR ZFREE
- NO_ZERO LDX BSSB
- JSR BFREE
- NO_BSSLDX DATAB
- JSR BFREE
- NO_DATALDX TEXTB
- JSR BFREE
- NO_TEXTRTS
-
- DO_LOAD; LOAD OPTIONS (I.E. IGNORE THEM NOW)
- JSR FGETC
- BCS NO_FILE
- CMP #0
- BEQ LOAD_TEXT
- TAY
- DEY
- OPTLJSR FGETC
- BCS NO_FILE
- DEY
- BNE OPTL
- BEQ DO_LOAD
-
- LOAD_TEXT; LOAD TEXT SEGMENT
- LDX FILE
- LDA #<TEXTA
- LDY #>TEXTA
- JSR FGETB
- BCS NO_FILE
-
- LDX FILE
- LDA #<DATAA
- LDY #>DATAA
- JSR FGETB
- BCS NO_FILE
- ; CHECK NUMBER OF UNDEFINED REFERENCES
- LDX FILE
- JSR FGETC
- &NO_FILE2 BCS NO_FILE
- CMP #0
- BNE NO_FILE; WE HAVE SOME -> NOT HANDLED
- LDX FILE
- JSR FGETC
- BCS NO_FILE
- CMP #0
- BNE NO_FILE
- ; OK, TEXT SEGMENTS LOADED, NOW RELOCATE
- LDA TEXTA
- SEC
- SBC #1
- STA P1
- LDA TEXTA+1
- SBC #0
- STA P1+1
- JSR TREL
-
- LDA DATAA
- SEC
- SBC #1
- STA P1
- LDA DATAA+1
- SBC #0
- STA P1+1
- JSR TREL
-
- LDA TEXTA; RETURN START OF TEXT SEGMENT
- LDY TEXTA+1
- CLC
- RTS
- .)
-
- TREL.(
- LDX FILE
- JSR FGETC
- NO_FILE1 BCS NO_FILE2
- CMP #0
- BEQ RELOC_RTS
- CMP #255
- BNE T1
- LDA #254
- CLC
- ADC P1
- STA P1
- BCC TREL
- INC P1+1
- JMP TREL
- T1CLC
- ADC P1
- STA P1
- BCC T1A
- INC P1+1
- T1A; P1 IS THE RELOCATION ADDRESS
- LDX FILE
- JSR FGETC
- BCS NO_FILE1
- TAY
- AND #a_mask
- STA TMP
- TYA
- AND #a_fmask
- JSR GETRELDIFF
- LDY TMP
- CPY #a_adr
- BNE T2
-
- LDY #0
- CLC
- ADC (P1),Y
- STA (P1),Y
- INY
- TXA
- ADC (P1),Y
- STA (P1),Y
- JMP TREL
- T2
- CPY #a_low
- BNE T3
- LDY #0
- CLC
- ADC (P1),Y
- STA (P1),Y
- JMP TREL
- T3
- CPY #a_high
- BNE TREL
- STA P2
- STX P2+1
- LDX FILE
- JSR FGETC
- CLC
- ADC P2; JUST GET THE CARRY BIT
- LDY #0
- LDA P2+1; RELOCATE HIGH BYTE
- ADC (P1),Y
- STA (P1),Y
- JMP TREL
-
- RELOC_RTS
- CLC
- RTS
- .)
-
- GETRELDIFF .(; COMPARING WITH seg_undef WOULD GIVE A WAY
- ; TO GET LABEL VALUE HERE FOR UNDEFINED REFS
- CMP #seg_text
- BNE NOTEXT
- LDA TEXTD
- LDX TEXTD+1
- RTS
- NOTEXTCMP #seg_data
- BNE NODATA
- LDA DATAD
- LDX DATAD+1
- RTS
- NODATACMP #seg_bss
- BNE NOBSS
- LDA BSSD
- LDX BSSD+1
- RTS
- NOBSSCMP #seg_zero
- BNE NOZERO
- LDA ZEROD
- LDX ZEROD+1
- NOZERORTS
- .)
-
- .)
-
- /**************************************************************************
- * hERE COME THE SUPPORT ROUTINES
- *
- * FIRST IS A SIMPLE AND BASIC IMPLEMENTATION OF FGETB, JUST USING FGETC
- */
-
- FGETB.(
- P=SYSZP
- -SYSZP+=2
- FILE=SYSMEM
- L=SYSMEM+1
- -SYSMEM+=3
-
- STX FILE; X=FILE, A=ZP-ADR OF ADDRESS, Y=ZP-ADR OF LEN
- STA P
- STY P+1
- LDY #3
- LDA (P),Y
- STA L+1
- DEY
- LDA (P),Y
- STA L
- DEY
- LDA (P),Y
- PHA
- DEY
- LDA (P),Y
- STA P
- PLA
- STA P+1
-
- LOOPLDX FILE
- JSR FGETC; THIS IS A SIMPLE IMPLEMENTATION
- BCS END
- LDY #0
- STA (P),Y
- INC P
- BNE L0
- INC P+1
- L0
- LDA L
- BNE L1
- DEC L+1
- L1DEC L
-
- LDA L
- ORA L+1
- BNE LOOP
- CLC
- END
- RTS
- .)
-
- /**************************************************************************
- * SUPPORT FOR MEMORY ALLOCATION
- *
- * tHESE ROUTINES ARE TAKEN FROM A PRELIMINARY slip IMPLEMENTATION, AS OF
- * os/a65 VERSION 1.3.10B
- */
-
- #DEFINEmaxslot8
-
- /**********************************************************************/
- /* nEW MEMORY MANAGEMENT FOR ip BUFFERS */
- /* EXPORTS */
- /* BINIT */
- /* BALLOC, BFREE, BTRUNC, BSPLIT, BREALLOC */
- /*GETBADR, GETBLEN */
-
- #DEFINEminbuf8
- #DEFINEminmask%11111000
-
- .(
-
- SLOTLADR =SYSMEM
- SLOTHADR =SYSMEM+maxslot
- SLOTLLEN =SYSMEM+maxslot*2
- SLOTHLEN =SYSMEM+maxslot*3
- -SYSMEM+=maxslot*4
-
- FLIST =SYSMEM
- SLOT=SYSMEM+2
- -SYSMEM+=3
-
- P=SYSZP
- P2=SYSZP+2
- P3=SYSZP+4
- P4=SYSZP+6
- -SYSZP+=8
-
- /* INIT MEMORY MANAGEMENT */
- &BINIT.(
- STA P+1; HI BYTE STARTADRESS BUFFER
- STX P2+1; HI BYTE LENGTH OF BUFFER
-
- LDA #0
- TAY
- L0STA SLOTLADR,Y
- STA SLOTHADR,Y
- INY
- CPY #maxslot
- BCC L0
-
- STA P
- TAY
- STA (P),Y
- INY
- STA (P),Y
- INY
- STA (P),Y
- INY
- LDA P2+1
- STA (P),Y
-
- LDA P
- STA FLIST
- LDA P+1
- STA FLIST+1
-
- CLC
- RTS
- .)
-
- /* A/Y = SIZE OF BUFFER TO BE ALLOCATED -> X BUFFER-id */
- &BALLOC.(
- /* WALK ALONG FREELIST, AND TAKE FIRST MATCHING BUFFER
- LENGTH IS MADE A MULTIPLE OF 8 (FOR FREELIST CONNECTORS */
-
- PHA
- JSR GETBSLOT
- PLA
- BCC GOTSLOT
- LDA #e_nomem
- RTS
- GOTSLOT
- STX SLOT
-
- ADC #minbuf-1
- AND #minmask
- STA SLOTLLEN,X
- TYA
- ADC #0
- STA SLOTHLEN,X
-
- LDA #0
- STA P2
- STA P2+1
- LDA FLIST
- STA P
- LDA FLIST+1
- STA P+1
- L0
- LDY #2
- LDA (P),Y
- SEC
- SBC SLOTLLEN,X
- STA P3
- INY
- LDA (P),Y
- SBC SLOTHLEN,X
- STA P3+1
- BCS FOUND
-
- LDA P
- STA P2
- LDA P+1
- STA P2+1
- LDY #1
- LDA (P2),Y
- STA P+1
- DEY
- LDA (P2),Y
- STA P
- ORA P+1
- BNE L0
-
- OOPSLDA #e_nomem
- SEC
- RTS
-
- FOUND
- /* OK, WE FOUND A FREE BUFFER: P POINTS TO THE BUFFER, P2 TO THE
- PREVIOUS ONE. P3 IS THE LENGTH OF THE FREE BUFFER MINUS THE
- NEEDED SIZE. iF THE BUFFER IS LONGER THAN NEEDED, CREATE A
- NEW FREE BUFFER, THEN LINK NEW BUFFER TO FREELIST */
-
- LDA P/* SAVE BUFFER ADDRESS */
- STA SLOTLADR,X
- LDA P+1
- STA SLOTHADR,X
-
- LDA P3 /* CHECK LENGTH */
- ORA P3+1
- BEQ NOCREATE
-
- LDA P/* GET ADDRESS OF NEW FREE BUFFER */
- CLC
- ADC SLOTLLEN,X
- STA P4
- LDA P+1
- ADC SLOTHLEN,X
- STA P4+1
-
- LDY #0/* COPY NEXT POINTER */
- LDA (P),Y
- STA (P4),Y
- INY
- LDA (P),Y
- STA (P4),Y
-
- INY/* SET NEW LENGTH */
- LDA SLOTLLEN,X
- STA (P),Y
- LDA P3
- STA (P4),Y
- INY
- LDA SLOTHLEN,X
- STA (P),Y
- LDA P3+1
- STA (P4),Y
-
- LDA P4
- STA P
- LDA P4+1
- STA P+1
-
- NOCREATE
- LDA P2
- ORA P2+1
- BEQ FREESTART
-
- LDY #0
- LDA P
- STA (P2),Y
- INY
- LDA P+1
- STA (P2),Y
- CLC
- BCC GETA
- FREESTART
- LDA P
- STA FLIST
- LDA P+1
- STA FLIST+1
- CLC
- GETA
- LDA SLOTLADR,X
- LDY SLOTHADR,X
- RTS
- .)
-
- /* FREE BUFFER (id=XR) */
- &BFREE.(
- LDA SLOTHADR,X
- STA P3+1
- LDA SLOTLADR,X
- STA P3
- ORA P3+1
- BEQ END2
-
- LDY #2
- LDA SLOTLLEN,X
- STA (P3),Y
- INY
- LDA SLOTHLEN,X
- STA (P3),Y
-
- LDA #0
- STA SLOTHADR,X
- STA SLOTLADR,X
-
- LDA FLIST
- ORA FLIST+1
- BNE OK/* NO FREE BUFFER SO FAR? */
-
- LDA P3
- STA FLIST
- LDA P3+1
- STA FLIST+1
- LDY #0
- TYA
- STA (P3),Y
- INY
- STA (P3),Y
- END2CLC
- RTS
- OK
- LDA #0
- STA P2
- STA P2+1
- LDA FLIST
- STA P
- LDA FLIST+1
- STA P+1
-
- /* WE HAVE TO FIND THE PLACE WHERE TO PUT THE BUFFER IN THE
- ORDERED FREE LIST. tHEN WE HAVE TO CHECK IF WE CAN MERGE
- FREE BUFFERS */
- LOOP
- LDA P3+1
- CMP P+1
- BCC FOUND
- BNE NEXT
- LDA P3
- CMP P
- BCC FOUND
- NEXT
- LDA P
- STA P2
- LDA P+1
- STA P2+1
- LDY #0
- LDA (P2),Y
- STA P
- INY
- LDA (P2),Y
- STA P+1
- ORA P
- BNE LOOP
- BEQ FOUND
- END
- CLC
- RTS
-
- FOUND/* P2 IS THE BUFFER BEFORE THE ONE TO BE FREED, P THE ONE BEHIND.
- P3 IS THE BUFFER TO BE INSERTED */
-
- LDA P2
- ORA P2+1
- BNE FOK
- ; INSERT BEFORE THE FIRST FREE BUFFER SO FAR
- LDY #0
- LDA FLIST
- STA (P3),Y
- INY
- LDA FLIST+1
- STA (P3),Y
- LDA P3
- STA FLIST
- LDY P3+1
- STY FLIST+1
- JSR BMERGE
- CLC
- RTS
- FOK; INSERT TO LIST
- LDY #1
- LDA P+1;LDA (P2),Y
- STA (P3),Y
- DEY
- LDA P;LDA (P2),Y
- STA (P3),Y
- LDA P3
- STA (P2),Y
- INY
- LDA P3+1
- STA (P2),Y
-
- LDA P3
- LDY P3+1
- JSR BMERGE
- LDA P2
- LDY P2+1
- JSR BMERGE
- CLC
- RTS
- .)
-
- /* GET ADRESS OF BUFFER */
- &GETBADR .(
- LDA SLOTLADR,X
- LDY SLOTHADR,X
- CLC
- RTS
- .)
-
- /* GET LENGTH OF BUFFER */
- &GETBLEN .(
- LDA SLOTLLEN,X
- LDY SLOTHLEN,X
- CLC
- RTS
- .)
-
- /* GET FREE BUFFER-id SLOT */
- GETBSLOT .(
- LDX #0
- L0
- CLC
- LDA SLOTLADR,X
- ORA SLOTHADR,X
- BEQ FOUND
- INX
- CPX #maxslot
- BCC L0
- FOUND
- RTS
- .)
-
- /* CHECK IF TWO BUFFERS (I.E. A/Y PLUS FOLLOWING) CAN BE MERGED */
- BMERGE.(
- STA P
- STY P+1
- LDY #2
- CLC
- LDA (P),Y
- ADC P
- STA P3
- INY
- LDA (P),Y
- ADC P+1
- STA P3+1
- LDY #0
- LDA (P),Y
- CMP P3
- BNE NOMERGE
- INY
- LDA (P),Y
- CMP P3+1
- BNE NOMERGE
- MERGE
- LDY #2
- CLC
- LDA (P3),Y
- ADC (P),Y
- STA (P),Y
- INY
- LDA (P3),Y
- ADC (P),Y
- STA (P),Y
- LDY #0
- LDA (P3),Y
- STA (P),Y
- INY
- LDA (P3),Y
- STA (P),Y
- NOMERGE
- CLC
- RTS
- .)
-
- .)
-
- prgend
-
-