home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
RCPM
/
LUXI80.LBR
/
MAKELUX.AZM
/
MAKELUX.ASM
Wrap
Assembly Source File
|
2000-06-30
|
9KB
|
446 lines
ORG 00100H
WBOOT EQU 00000H
BDOS EQU 00005H
DEFFCB EQU 00080H
;
CR EQU 00DH
LF EQU 00AH
;
CHROUT EQU 002H
OPNFIL EQU 00FH
CLSFIL EQU 010H
FNDFIL EQU 011H
DELFIL EQU 013H
RDREC EQU 014H
WRTREC EQU 015H
MAKFIL EQU 016H
SETDMA EQU 01AH
;
START: LXI H,0
DAD SP
SHLD TMPSTK ;Save STACK for later (self-modifying code)
LXI SP,LOADER+080H
;
LXI D,DEFFCB
MVI C,SETDMA ;Use default FCB for DIR searches
CALL BDOS
;
LXI D,CO0FCB
MVI C,FNDFIL
CALL BDOS ;Go search for LUX.CO0
INR A ;Is it there?
JNZ FNDCO1 ;Yes
CALL ILPRT
DB 'Can''t find LUX.CO0 - Aborting',CR,LF,0
JMP EXIT ;Nope - display error and return
;
FNDCO1: LXI D,CO1FCB
MVI C,FNDFIL
CALL BDOS ;Go search for LUX.CO1
INR A ;Is it there?
JNZ OPNCO0 ;Yes
CALL ILPRT
DB 'Can''t find LUX.CO1 - Aborting',CR,LF,0
JMP EXIT ;Nope - display error and return
;
OPNCO0: LXI D,CO0FCB
MVI C,OPNFIL
CALL BDOS ;Open LUX.CO0 for input
CPI 0FFH ;Open OK?
JNZ GETCO0 ;Yes - go read it then
CALL ILPRT
DB 'LUX.CO0 open error',CR,LF,0
JMP EXIT ;Nope - display error and return
;
GETCO0: LXI H,RDSPC
LXI D,080H
GETC0A: DAD D ;Calc next sector address
XCHG
PUSH D
PUSH H
MVI C,SETDMA
CALL BDOS ;Tell BDOS where to put LUX.CO0 sector
LXI D,CO0FCB
MVI C,RDREC
CALL BDOS ;Read a record of LUX.CO0
POP H
POP D
XCHG
ORA A ;All of file in yet?
JZ GETC0A ;Nope - go read another sector
SHLD CO0END ;Yes. Save "end of LUX.CO0" pointer
;
LXI D,CO1FCB
XRA A
STA CO1EXT
STA CO1REC ;Init current extent and record to read
MVI C,OPNFIL
CALL BDOS ;Open LUX.CO1
CPI 0FFH ;Open OK?
JNZ GETCO1 ;Yes
CALL ILPRT
DB 'LUX.CO1 open error',CR,LF,0
JMP EXIT ;Nope - display error and return
;
GETCO1: LXI H,CO0DAT ;<HL> points to LUX.CO0 data
LXI D,LNKMAP ;<DE> points to our link map
;
GETC1A: XRA A ;Clear <A>
STAX D ;Zero out a byte of the link map
MVI B,008H ;Prepare to process 8 bytes of LUX.CO0
;
GETC1B: CALL GETBYT ;Fetch a byte of LUX.CO1
JC MAKLEN ;Jump if end of file on LUX.CO1
CMP M ;Is this byte of LUX.CO1 same as LUX.CO0?
JZ GETC1C ;Yes - so it's absolute
STC ;No - it's relative
;
GETC1C: LDAX D
RAL
STAX D ;Tag the bit corresponding to this byte
INX H ;Next byte of LUX.CO0...
DCR B
JNZ GETC1B ;Process all 8 bits of this link map entry
INX D ;Point to next byte of link map
JMP GETC1A ; and do it all over again
;
MAKLEN: LHLD CO0END
LXI D,CO0DAT
MOV A,L
SUB E
MOV L,A
MOV A,H
SBB D
MOV H,A ;Calc length of LUX.CO0 (in <HL>)
MOV A,L
ORA A ;Is length of form 0XX00h?
JZ MKLEN1 ;Yup
MVI L,0
INR H ;Nope, so force it that way (add 128 bytes)
MKLEN1: SHLD CO0LEN ; and save that length away
LXI D,LODLEN
DAD D ;Add the length of the loader to LUX.CO0 length
MOV A,L
ORA A ;Is length in the form 0XX00h?
JZ MKLEN2 ;Yup
CPI 080H ;Well then, is it in the form 0XX80?
JZ MKLEN2 ;Yup
MVI L,0
INR H ;Nope, so force it to be a multiple of sector
;
MKLEN2: MVI B,7
MKLEN3: MOV A,H
RRC
MOV H,A
MOV A,L
RAR
MOV L,A
DCR B
JNZ MKLEN3 ;Divide this length by the sector size (080h)
; MOV A,L
STA LODKNT ;Save the sector count
;
LXI D,COMFCB
MVI C,DELFIL
CALL BDOS ;Delete any old LUX.COM file
LXI D,COMFCB
MVI C,MAKFIL
CALL BDOS ;Create a new LUX.COM file
CPI 0FFH ;Could we create the file?
JNZ WRTCOM ;Yes - go write it then
CALL ILPRT
DB 'No directory space',CR,LF,0
JMP EXIT ;Nope - display error and return
;
WRTCOM: LXI H,LOADER
LXI D,080H
LDA LODKNT
MOV B,A ;Sector count to <B>
;
WTCOM1: DAD D ;Calc next sector address
XCHG
PUSH B
PUSH D
PUSH H ;We use all regs, so save em
MVI C,SETDMA
CALL BDOS ;Tell BDOS where to get the data
LXI D,COMFCB
MVI C,WRTREC
CALL BDOS ;Write a record of LUX.COM
POP H
POP D
POP B ;Get all our regs back
;
XCHG
ORA A ;Did we get an error on that last write?
JNZ WTCOM2 ;Yes - disk must be full then
DCR B
JNZ WTCOM1 ;Nope - go write another record then
;
LXI D,COMFCB
MVI C,CLSFIL
CALL BDOS ;Go close the file now
CPI 0FFH ;Sucessful close?
JNZ EXIT ;Yes - all done. LUX.COM is ready!!!
;
WTCOM2: CALL ILPRT
DB 'Disk full - aborting',CR,LF,0
;
LXI D,COMFCB
MVI C,CLSFIL
CALL BDOS ;Try to close the file again
LXI D,COMFCB
MVI C,DELFIL
CALL BDOS ;Delete the bad file
EXIT: LXI SP,$-$
TMPSTK EQU $-2
RET ;We now return you to the system
;
GETBYT: PUSH B
PUSH D
PUSH H
GTBYT1: LDA BYTKNT
INR A
STA BYTKNT
CPI 081H
JZ GETREC
LHLD LODADR
MOV A,M
INX H
SHLD LODADR
POP H
POP D
POP B
ORA A
RET
;
GETREC: XRA A
STA BYTKNT
LXI H,DEFFCB
SHLD LODADR ;Reset data address
XCHG ;<DE> gets default FCB address
MVI C,SETDMA
CALL BDOS
LXI D,CO1FCB
MVI C,RDREC
CALL BDOS
ORA A
JZ GTBYT1
POP H
POP D
POP B
STC
RET
;
ILPRT: XTHL
ILPRT1: MOV A,M
ORA A
JZ ILPRT2
CALL CTYPE
INX H
JMP ILPRT1
;
ILPRT2: XTHL
RET
;
CTYPE: PUSH PSW
PUSH B
PUSH D
PUSH H
ANI 07FH
MOV E,A
MVI C,CHROUT
CALL BDOS
POP H
POP D
POP B
POP PSW
RET
;
LODADR: DW 0
BYTKNT: DB 128
LODKNT: DB 0
CO0END: DW 0
CO0FCB: DB 0 ;Current drive
DB 'LUX CO0' ;File name
DB 0,0,0,0,0,0,0,0 ;Rest of FCB
DB 0,0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0,0
CO1FCB: DB 0 ;Current drive
DB 'LUX CO1' ;File name
CO1EXT: DB 0,0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0,0
DB 0,0,0,0
CO1REC: DB 0,0,0,0
COMFCB: DB 0 ;Current drive
DB 'LUX COM' ;File name
DB 0,0,0,0,0,0,0,0 ;Rest of FCB
DB 0,0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0,0
;
; Start the loader at 0XX00h just to make it look nice
;
ORG ($+0FFH) AND 0FF00h
;
; The following loader is placed in the beginning of LUX.COM,
; followed by the LINK MAP and finally, LUX.CO0. The loader
; examines top of memory, allows enough space for LUX to
; reside in, and relocates LUX.CO0 (the 0 absolute version)
; to this area, changing all relative bytes to absolute by
; adding in the offset of where LUX.CO0 is being moved. The
; loader accomplishes this by using the LINK MAP created above.
;
OFFSET EQU $-100H
LOADER EQU $-080H
;
LODBEG EQU $
CALL LOCATE ;Locate a place for LUX and link it there
;
LHLD C0LENR
MOV B,H
MOV C,L
LHLD LDADDR
XCHG
LXI H,C0DATR
;
TMP010 EQU $-OFFSET
MOV A,M
INX H
XCHG
MOV M,A
INX H
XCHG
DCR C
JNZ TMP010
DCR B
JNZ TMP010 ;Move LUX to our new-found area
;
LHLD LDADDR
PCHL ; and go run it!!!
;
LOCATE EQU $-OFFSET
LDA BDOS+1
CPI 006H ;Has LUX modified BIOS vectors already?
JNZ LINK ;Yes - just link it then
;
LHLD WBOOT+1
MVI B,004H ;Prepare to find a place for LUX to reside
;
LOCAT1: EQU $-OFFSET
INX H ;Skip the JMP opcode byte
MOV E,M
INX H
MOV D,M ;<DE> has address of a BIOS routine
INX H ;<HL> points to next BIOS jump vector
; PUSH H ; so save it
;
MOV A,L
SUB E
MOV A,H
SBB D ;Is this BIOS routine below its jump vector?
; POP H
JNC LINK ;Yes - use it then for top of memory
DCR B
JNZ LOCAT1 ;No - better find another then
;
; None of the vectors reference routine below their vectors, so
; we can assume all of memory below the Warm Start vector is free
; for use.
;
LHLD WBOOT+1 ;Get address of Warm Boot vector
LXI D,0F203H
DAD D ;Point back to where BDOS vectors should be
;
XCHG
LHLD BDOS+1 ;Get BDOS vector address
XCHG ; into <DE>
MOV A,E
CMP L ;Are the two the same?
JNZ LINK ;Nope. Better use BDOS address then
MOV A,D
CMP H ;Are they *really* the same?
JNZ LINK ;Nope. Better use BDOS address then
JMP LINK1 ;Yes, so we know BDOS is safe to use
;
LINK EQU $-OFFSET
LHLD BDOS+1
DCR H ;Use BDOS address - 256 for safety
JMP LINK2
;
LINK1 EQU $-OFFSET
LHLD BDOS+1 ;Safe to use BDOS address directly
LINK2 EQU $-OFFSET
MVI L,0 ;Start at an even boundary
;
XCHG
LHLD C0LENR ;Get LUX length
XCHG ; into <DE>
MOV A,L
SUB E
MOV L,A
MOV A,H
SBB D
MOV H,A ;Subtract LUX length from our address
SHLD LDADDR ; which becomes the load point
;
MOV C,H ;<C> has LOAD offset for linking
LHLD C0LENR
XCHG ;<DE> has LUX length
LXI H,LKMAPR
SHLD IXPTR ;<IXPTR> has LINK MAP address
LXI H,C0DATR ;<HL> has LUX address
;
LINK3 EQU $-OFFSET
MVI B,8 ;Prepare for 8 bytes of processing
LINK4 EQU $-OFFSET
PUSH H
LHLD IXPTR ;Get <IXPTR>
MOV A,M
RAL ;Is this byte absolute or relative
MOV M,A
POP H
JNC LINK5 ;Absolute - don't offset it then
MOV A,M
ADD C
MOV M,A ;Relative - offset it by the load address
LINK5 EQU $-OFFSET
INX H ;Next byte of raw LUX code
DCX D
MOV A,E
ORA D ;Done all of LUX yet?
RZ ;Yes - linking is complete
DCR B
JNZ LINK4 ;No - go do another byte of LUX
;
PUSH H
LHLD IXPTR
INX H ;Point to next byte of LINK MAP
SHLD IXPTR
POP H
JMP LINK3 ; and go process 8 more bytes of LUX
;
C0LENR EQU $-OFFSET
CO0LEN: DW 0
LDADDR EQU $-OFFSET
DW 0
IXPTR EQU $-OFFSET
DW 0
;
; ADDRESS = 00480h
;
LKMAPR EQU $-OFFSET
LNKMAP: DS 128
DS 128
DS 128
DS 128
DS 128
DS 128
;
; LUX.CO0 follows this program and goes below:
;
C0DATR EQU $-OFFSET
CO0DAT EQU $
RDSPC EQU CO0DAT-080H
LODLEN EQU CO0DAT-LODBEG
END