home *** CD-ROM | disk | FTP | other *** search
- ; ╔═════════════════════════════════════════════════════════════╗
- ; ║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
- ; ║░░░░░░░░░░░░░░░░╔═╗░╔═╗░╦░╦░═╦═░╦░╦═╗░╔══░╔═╗░░░░░░░░░░░░░░░░║
- ; ║░░░░░░░░░░░░░░░░╠╦╝░║░║░║░║░░║░░║░║░║░╠═░░╚═╗░░░░░░░░░░░░░░░░║
- ; ║░░░░░░░░░░░░░░░░╩╚═░╚═╝░╚═╝░░╩░░╩░╩░╩░╚══░╚═╝░░░░░░░░░░░░░░░░║
- ; ║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
- ; ╚═════════════════════════════════════════════════════════════╝
- ;╔════════════════╗
- ;║ SETEVAR ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ │
- ; │ Set a system environment variable │
- ; │ │
- ; │ DS:SI - location of variable name (input) │
- ; │ │
- ; │ CARRY set if not done │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@SETEVAR
- $SETEVAR: PUSH AX,BX,CX,DX,ES,DI
- DELEVAR ;delete the old variable first
- GETENV ;find the environment
- JC >L2
- MOV BX,CX ;save the length of the environment
- XOR AX,AX ;clear AX
- L1: REPNZ SCASB ;find the next variable
- ES CMP B[DI],0 ;are we at the very end?
- JNZ L1 ;no - keep going
- CALL >L3 ;swap DS:SI <--> ES:DI
- MOV DX,DI ;DX = start of new variable
- MOV CX,0100 ;CX = a long length
- REPNZ SCASB ;find the null
- SUB DI,DX ;DX = length of new variable
- XCHG DI,DX
- CALL >L3 ;swap back
- SUB BX,DI ;BX = leftover in environment
- SUB BX,12 ;reduce by twelve bytes
- CMP BX,DX ;is there enough room ?
- JC >L2 ;no - jump as error
- PUSH SI,DI,DS
- MOV SI,DI ;align source and destination
- ADD DI,DX ;point to new end
- MOV DS,ES ;align segments
- MOV CX,DX ;set up the length
- REP MOVSB ;move the tail upward
- MOV CX,DX ;set up length again
- POP DS,DI,SI
- REP MOVSB ;move in the new value
- CLC ;everything is all right
- L2: POP DI,ES,DX,CX,BX,AX
- RET
- L3: PUSH DS,SI,ES,DI ;swap DS:SI <--> ES:DI
- POP SI,DS,DI,ES
- RET
- #ENDIF
- ;╔════════════════╗
- ;║ DELEVAR ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Delete a system environment variable │
- ; │ │
- ; │ DS:SI - location of variable name │
- ; │ │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@DELEVAR
- $DELEVAR: PUSH AX,BX,CX,DS,SI,ES,DI
- GETENV ;find the environment
- JC >L2 ;exit if it isn't found
- MOV BX,CX ;save the displacement of end
- GETEVAR ;find the variable
- JC >L2 ;exit if it doesn't exist now
- L0: DEC DI ;back up one character
- JZ >L1 ;stop if at beginning of environment
- ES CMP B[DI-1],0 ;are we back at the null ?
- JNZ L0 ;no - keep going
- L1: PUSH ES,DI ;save location
- XOR AX,AX ;AX=0
- MOV CX,0100 ;length=256 bytes
- REPNZ SCASB ;look forward for a null
- MOV DS,ES ;DS:SI <-- next part of environment
- MOV SI,DI ;ES:DI <-- deletable part
- POP DI,ES
- MOV CX,BX ;save the environment length
- SUB CX,SI ;calculate length left
- REP MOVSB ;delete the item
- L2: POP DI,ES,SI,DS,CX,BX,AX
- RET
- #ENDIF
- ;╔════════════════╗
- ;║ GETEVAR ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ │
- ; │ Get address of a system environment variable │
- ; │ │
- ; │ DS:SI - location of variable name (input) │
- ; │ │
- ; │ ES:DI - location of environment's variable │
- ; │ CX - available room in environment │
- ; │ CARRY set if variable not found │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@GETEVAR
- $GETEVAR:GETENV ;find the environment
- JC >L4 ;reject if not found
- PUSH AX
- L1: PUSH SI ;tuck it in the stack
- L2: LODSB ;get a letter
- SCASB ;does it match ?
- JNZ >L3 ;no - drop this
- CMP AL,"=" ;is it the end of variable ?
- JNZ L2 ;no - vanish
- PUSH DI ;save this displacement
- GETENVT ;get the size
- POP DI,SI,AX ;reset the stack
- RET
- L3: XOR AX,AX ;look for a null
- REPNZ SCASB ;have we found it ?
- POP SI ;reset stack
- ES CMP B[DI],0 ;is this the end of environment ?
- JNZ L1
- POP AX ;reset the stack
- L4: GETENVT ;get remainder
- STC ;mark problem
- RET
- #ENDIF
- ;╔════════════════╗
- ;║ GETENVT ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ │
- ; │ Get address of system environment tail │
- ; │ │
- ; │ ES:DI - location of environment's tail │
- ; │ CX - available room in environment │
- ; │ CARRY set if no room found │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@GETENVT
- $GETENVT: PUSH AX ;save AX
- GETENV ;get address of environment
- JC RET ;exit if not found
- XOR AX,AX ;looking for a NULL
- L1: REPNZ SCASB ;stop at the null
- ES CMP B[DI],0 ;is it the double-null ?
- JNZ L1 ;no - keep looking
- POP AX ;restore AX
- SUB CX,12 ;allow distance of twelve
- JA RET ;jump if enough room
- XOR CX,CX ;clear down to zero
- STC ;set carry (error)
- RET
- #ENDIF
- ;╔════════════════╗
- ;║ GETENV ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Get address of system environment │
- ; │ │
- ; │ ES:DI - location of environment │
- ; │ CX - length of environment │
- ; │ CARRY set if environment not found │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@GETENV
- $GETENV: PUSH AX,BX,DX,SI
- MOV DX,CS ;point to own PSP
- MOV CX,10 ;max depth = ten
- L0: MOV ES,DX ;point to a PSP
- CMP DX,0A000 ;is it in high memory ?
- JA >L1 ;yes - should be DRDOS
- ES CMP DX,[016] ;is this its own father ?
- ES MOV DX,[016] ;(regardless - activate father)
- LOOPNZ L0 ;not father - go deeper
- JCXZ >L9 ;problem if too deep
- L1: MOV DI,DX ;point to the PSP
- ES MOV BX,[02C] ;pick up pointer to environment
- CMP BX,0 ;is it blank ?
- JZ >L7 ;yes - jump (still might be good)
- PUSH BX,DX,DI ;(save registers)
- MOV AH,030 ;get DOS version number
- INT 021 ;DOS service interrupt
- CMP AX,0A03 ;is this version 3.10 ?
- JZ >L4 ;yes - problems!
- CS MOV ES,[02C] ;pick up pointer to own environment
- MOV SI,O >K0 ;we shall look for proof of DRDOS
- XOR DI,DI ;start at beginning of environment
- MOV CX,2000 ;max length to search
- L2: XOR BX,BX ;start at displacement zero
- L3: MOV AL,[SI+BX] ;pick up a byte from footprint
- ES CMP AL,[DI+BX] ;is this byte a match ?
- JNZ >L6 ;no - keep looking
- INC BX ;increment
- CMP BX,5 ;have we found all the toes ?
- JB L3 ;not yet - keep looking
- L4: POP DI,DX,BX ;(restore registers)
- MOV DX,BX ;this is the (putative) environment
- DEC DX ;back up to its arena
- L5: MOV ES,DX ;activate arena
- ES CMP DI,[1] ;does this "belong" to the PSP ?
- JNZ >L8 ;no - we must go searching
- ES CMP B[010],020 ;yes - is the first byte alphabetic ?
- JB >L8 ;not alphabetic - go searching again
- ES MOV CX,[3] ;pick up length of this partition
- INC DX ;go back to putative environment
- MOV ES,DX ;this IS the environment
- MOV AX,16 ;multiply paragraphs by sixteen..
- MUL CX ;..to establish environment size in AX
- MOV CX,AX ;store the environment size
- JMP S >L9 ;exit now
- L6: XOR AX,AX ;(clear AX)
- REPNZ SCASB ;look for the next operand
- ES CMP AL,[DI] ;are we at the end of environment ?
- JNZ L2 ;no - keep looking for footprint
- POP DI,DX,BX ;(restore regs) now at end of environment
- L7: DEC DX ;back up to arena
- MOV ES,DX ;activate it
- L8: ES ADD DX,[3] ;point to end of this partition
- INC DX ;bump to next partition
- MOV BX,CS ;pick up current PSP
- CMP DX,BX ;have we arrived yet ?
- JNA L5 ;not yet - keep trying
- XOR CX,CX ;troubles - not found
- L9: POP SI,DX,BX,AX
- XOR DI,DI
- STC
- JCXZ RET
- CLC
- RET ;go out
- K0 DB 'OS=DR'
- #ENDIF
- ;╔════════════════╗
- ;║ ERROR ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝Errors are accessed in "ERRORS" via BP. │
- ; │ This routine reports and then resigns with │
- ; │ ERRORLEVEL = BP. "Conditional" entry via │
- ; │ ERRIFccc < Z, NZ, C, NC, B, A >. │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@ERROR
- @@ERRDFT = 1
- $ERRIFZ: JZ $ERROR
- RET
- $ERRIFNZ:JNZ $ERROR
- $ERRIFA: JA $ERROR
- RET
- $ERRIFB: JC $ERROR
- RET
- $ERRIFNC:JC RET
- $ERROR: MOV DX,O >E9-14 ;point to start of default msg
- MOV SI,O $$ERRORS ;point to error table
- MOV AX,BP ;set the error into AX
- CALL $ERRDFT ;look up the error
- ABORT ;abort
- #ENDIF
- ;╔════════════════╗
- ;║ PRIOERR ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Print I/O error (if Cflag on) │
- ; │ input = AX │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@PRIOERR
- @@ERRDFT = 1
- $PRIOERR:JNC RET
- PUSH CX,DX,BP,SI
- MOV DX,O >E9-18 ;point to start of default msg
- MOV SI,O >L1 ;point to error table
- MOV BP,AX ;synchronise BP and AX
- CALL $ERRDFT ;look up the error & print it
- POP SI,BP,DX,CX
- STC
- RET
- L1:
- ASCIIZ "Invalid function" ;01
- ASCIIZ "File not found" ;02
- ASCIIZ "Path not found" ;03
- ASCIIZ "No available handle" ;04
- ASCIIZ "Access denied" ;05
- ASCIIZ "Unauthorised function" ;06
- ASCIIZ "MCB destroyed" ;07
- ASCIIZ "Insufficient memory" ;08
- ASCIIZ "Invalid address" ;09
- ASCIIZ "Invalid environment" ;0A
- ASCIIZ "Invalid format" ;0B
- ASCIIZ "Invalid access mode" ;0C
- ASCIIZ 0FF ;0D
- ASCIIZ 0FF ;0E
- ASCIIZ "Invalid device" ;0F
- ASCIIZ
- #ENDIF
- ;╔════════════════╗
- ;║ ERRDFT ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ DX <-- message nnn from table at SI │
- ; │ or default "ERROR nnn" AX=nnn (registers not saved) │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@ERRDFT
- @@CRLF = 1
- $ERRDFT :PUSH SI ;save addr of error table
- MOV SI,O >E9 ;point to bin store
- MOV W[SI],AX ;store nnn
- LEA DI,[SI-8] ;point to decimal expansion
- MOV ES,DS ;synchronise segments
- WBINTODEC ;conv to dec
- POP SI ;get addr of error table
- LOOKUP ;lookup entry nnn
- JC >L1 ;jump if not found
- CMP W[SI],0FF ;empty entry ?
- IF NZ MOV DX,SI ;if found, DX = message
- L1:
- NLPRINT ;print it
- JMPL $CRLF ;line feed
- DB "I/O ERROR "
- DB 8 DUP 0
- E9 DW 0
- #ENDIF
- ;╔════════════════╗
- ;║ LOOKUP ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Lookup into table (DS:SI) to item N │
- ; │ BP = item number (N) - starts at 1 │
- ; │ SI updated - carry set if not found │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@LOOKUP
- $LOOKUP: PUSH AX,CX
- LEA CX,[BP-1]
- JCXZ >L2
- L1: LODSB
- TEST AL
- JNZ L1
- TEST B[SI]
- JZ >L2
- LOOP L1
- L2: CMP B[SI],1
- POP CX,AX
- RET
- #ENDIF
- ;╔════════════════╗
- ;║ DBINTODEC ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ DOUBLEWORD Binary to Decimal │
- ; │ i/p : DX | AX │
- ; │ o/p : at DI with length CX (not counting 0,$) │
- ; │ max space taken up is 15 bytes: max CX=000D (13) │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@DBINTODEC
- @@WBINTODEC = 1
- $DBINTODEC: PUSH DX
- JMP S >L0
- #ENDIF
- ;╔════════════════╗
- ;║ WBINTODEC ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ WORD Binary to Decimal │
- ; │ i/p : AX │
- ; │ o/p : at DI with length CX (not counting 0,$) │
- ; │ max space taken up is 8 bytes: max CX=0006 │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@WBINTODEC
- $WBINTODEC: PUSH DX ;save registers on input
- XOR DX,DX ;no HIGH part to doubleword
- L0: PUSH AX,BX,SI,DI
- MOV SI,O >L9 ;point to the table
- MOV CX,10 ;putative decimal counter
- XOR BX,BX ;clear significance pointer
- L1: XOR BL,BL ;clear the low byte
- L2: CMP DX,[SI+2] ;is the table entry too large ?
- JZ >L4 ;probably - try the other side!
- JNA >L5 ;yes - so jump
- L3: SUB AX,[SI] ;reduce DX.AX by D[SI]
- SBB DX,[SI+2]
- INC BL ;count this
- JMP L2 ;repeat testing
- L4: CMP AX,[SI] ;is the table entry too large ?
- JNB L3 ;no - jump to reduce
- L5: PUSH AX,DX ;save the residue
- CMP CX,1 ;are we at the end of digits ?
- JZ >L6 ;yes - this is significant ANYWAY
- TEST BH ;has significance been found ?
- JNZ >L6 ;yes - no zero-suppression
- TEST BL ;is the digit a leading zero ?
- JZ >L8 ;yes - finished this iteration
- MOV BH,1 ;indicate significance started
- L6: ADD BL,'0' ;make it printable
- MOV AL,BL ;set it for storing to output
- STOSB
- CMP CL,4 ;are we at a comma-break ?
- JZ >L7
- CMP CL,7
- JZ >L7
- CMP CL,10
- JNZ >L8
- L7: MOV AL,',' ;arrange a comma character
- STOSB
- L8: POP DX,AX ;restore residue
- ADD SI,4 ;move down table
- LOOP L1 ;keep going for all digits
- MOV W[DI],'$' by 0 ;append terminators
- MOV CX,DI ;pick up current location
- POP DI ;retrieve original location
- SUB CX,DI ;calculate length
- POP SI,BX,AX,DX ;retrieve registers
- RET
- L9: DD 1000000000
- DD 100000000
- DD 10000000
- DD 1000000
- DD 100000
- DD 10000
- DD 1000
- DD 100
- DD 10
- DD 1
- #ENDIF
- ;╔════════════════╗
- ;║ WDECTOBIN ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ WORD Decimal to Binary │
- ; │ i/p : at SI │
- ; │ cf if error o/p : AX │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@WDECTOBIN
- $WDECTOBIN:PUSH CX,DX,SI
- XOR CX,CX ;clear the result
- L1: LODSB ;pick up one byte
- CMP AL,0 ;are we at the end?
- JZ >L3 ;yes - finished
- CMP AL,"," ;is it a comma?
- JZ L1 ;yes - omit
- VALIDNUM ;test whether valid numeric
- JC >L2 ;no - finished with error
- CBW ;extend AL into AX
- XCHG AX,CX ;get the result
- MUL W >L4 ;multiply by ten
- ADD CX,AX ;accumulate
- OR DX,DX ;was there overflow?
- JZ L1 ;no - keep going
- L2: XOR CX,CX ;clear total
- STC ;set error
- L3: MOV AX,CX
- POP SI,DX,CX
- RET
- L4 DW 10
- #ENDIF
- ;╔════════════════╗
- ;║ VALIDHEX ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ VALIDHEX: validate a byte as HEX │
- ; │ i/p - AL │
- ; │ o/p - AL (binary equivalent) │
- ; │ Zflag set if good │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@VALIDHEX
- $VALIDHEX:
- VALIDNUM ;SEE IF IT IS NUMERIC
- JZ RET ;IF SO, THIS IS GOOD
- AND AL,0DF ;CONVERT TO UPPERCASE
- CMP AL,011
- JB RET
- CMP AL,016
- JA >L2
- SUB AL,7
- JMP >L1
- #ENDIF
- ;╔════════════════╗
- ;║ VALIDNUM ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ VALIDNUM: validate a byte as NUMERIC │
- ; │ i/p - AL │
- ; │ o/p - AL (binary equivalent) │
- ; │ Zflag set if good │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@VALIDNUM
- $VALIDNUM:SUB AL,030 ;CONVERT TO BINARY
- JB RET
- CMP AL,9
- JA >L2
- L1: CMP AL,AL ;FORCE Z FLAG ON
- RET
- L2: STC
- RET
- #ENDIF
- ;╔════════════════╗
- ;║ FRJULIAN ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Calculate day/month/year from Julian date │
- ; │ │
- ; │ i/p: BX = "Julian" date │
- ; │ │
- ; │ o/p: AL = day (0=Sunday, 1=Monday..) │
- ; │ CX = year (including century) │
- ; │ DH = month │
- ; │ DL = day │
- ; ├─────────────────────────────────────────────────────────────┤
- ; │ The "Julian" date here is the number of days since │
- ; │ 20th November 1937: it applies to all dates from then │
- ; │ up to 31st December 2099. It is related to the │
- ; │ Clarion date and to Scaliger's date function. │
- ; │ │
- ; │ Clarion = Julian + 50,000 │
- ; │ Scaliger = Julian + 2,428,858 │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@FRJULIAN
- $FRJULIAN:
- WEEKDAYJ
- PUSH AX,BX,BP
- MOV AX,BX
- XOR DX,DX
- ADD AX,0360E ;adjust for later division
- ADC DX,0
- PUSH AX ;save (low part only!)
- DSAL DX,AX ;calculate "yyyy" -> mult by 4
- DSAL DX,AX
- MOV CX,365*4 + 1 ;divide by 365.25 to find year
- DIV CX
- MOV BP,1900 ;use 20th century
- ADD BP,AX ;BP <- "yyyy"
- MUL CX
- SHR AX,1
- SHR AX,1
- POP CX
- SUB CX,AX ;isolate "B" (days into year)
- AND CX,01FF
- CMP CX,60 ;before 60 ?
- JNB >L2 ;no - jump
- TEST BP,3 ;leap year ?
- IF Z INC CL ;yes - adjust working number
- CMP CL,32 ;before 32 ?
- MOV CH,1 ;assume January
- IF NB ADD CX,0100 - 31 ;no - adjust
- L1: MOV DX,CX ;DX <- mm & dd
- MOV CX,BP ;CX <- yyyy
- POP BP,BX,AX
- RET
- L2: MOV AX,100 ;calculate "mm"
- MUL CX
- ADD AX,3225
- MOV BX,3060
- XOR DX,DX
- DIV BX ;AX <- "mm"
- PUSH AX ;save it
- MUL BX ;calculate "C"
- SUB AX,3240
- MOV BX,100
- DIV BX ;AX <- "C"
- SUB CX,AX ;CX <- "dd"
- POP AX ;retrieve "mm"
- MOV CH,AL ;CX <- "mm" & "dd"
- JMP L1
- #ENDIF
- ;╔════════════════╗
- ;║ TOJULIAN ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Calculate Julian date from day/month/year │
- ; │ │
- ; │ i/p: CX = year (including century) │
- ; │ DH = month │
- ; │ DL = day │
- ; │ │
- ; │ o/p: AL = day (0=Sunday, 1=Monday..) │
- ; │ BX = "Julian" date │
- ; ├─────────────────────────────────────────────────────────────┤
- ; │ The "Julian" date here is the number of days since │
- ; │ 20th November 1937: it applies to all dates from then │
- ; │ up to 31st December 2099. It is related to the │
- ; │ Clarion date and to Scaliger's date function. │
- ; │ │
- ; │ Clarion = Julian + 50,000 │
- ; │ Scaliger = Julian + 2,428,858 │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@TOJULIAN
- @@WEEKDAYJ = 1
- $TOJULIAN: PUSH AX,CX,DX,BP
- XOR AX,AX
- XCHG AL,DH ;AX <-- month
- PUSH AX
- MOV BP,DX ;BX <-- term1
- MOV DX,306
- MUL DX
- ADD AX,26
- MOV BX,10
- DIV BX
- ADD BP,AX ;BP += term2
- POP AX ;retrieve month
- CMP AL,2 ;JAN or FEB ?
- JA >L1 ;no
- ADD BP,AX ;yes - add on factor
- TEST CL,3 ;leap year ?
- IF NZ INC BP ;no - bump up BP
- L1: SUB CX,1900 ;calculate term3
- MOV AX,365 ;days in year
- MUL CX
- SHR CX,1 ;..plus the quarter-day
- SHR CX,1
- ADD AX,CX
- ADD AX,0C9CF ;add corrective factor
- ADD AX,BP ;accumulate the extra
- MOV BX,AX ;BX <-- result
- POP BP,DX,CX,AX
- ;>> fall through
- #ENDIF
- ;╔════════════════╗
- ;║ WEEKDAYJ ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Calculate weekday from a Julian date │
- ; │ │
- ; │ i/p: BX = "Julian" date │
- ; │ o/p: AL = day (0=Sunday, 1=Monday..) │
- ; ├─────────────────────────────────────────────────────────────┤
- ; │ The "Julian" date here is the number of days since │
- ; │ 20th November 1937: it applies to all dates from then │
- ; │ up to 31st December 2099. It is related to the │
- ; │ Clarion date and to Scaliger's date function. │
- ; │ │
- ; │ Clarion = Julian + 50,000 │
- ; │ Scaliger = Julian + 2,428,858 │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@WEEKDAYJ
- $WEEKDAYJ: PUSH BX,CX
- MOV CH,AH ;save AH
- LEA AX,[BX+6] ;adjust BX result by six days
- L1: XOR BX,BX ;AX =(date%256) and BX =(date/256)
- XCHG AH,BL ;calculate effect of BX
- SHL BX,1
- SHL BX,1
- ADD AX,BX
- MOV BH,7 ;set up divisor
- CMP AH,BH ;is dividend small enough yet ?
- JNB L1 ;no - go around once again
- DIV BH ;yes - calculate modulo 7
- MOV AL,AH ;record the result in AL
- MOV AH,CH ;retrieve AH
- POP CX,BX
- RET
- #ENDIF
- ;╔════════════════╗
- ;║ SWAPSCR ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ │
- ; │ Swap memory (DS:SI) with screen (segment ES) │
- ; │ 1st word = row/col 2nd word = rows/cols others = bytes│
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@SWAPSCR
- $SWAPSCR: PUSH BX,CX,DX,SI,DI,BP,AX
- LODSW ;PICK UP LOCATION
- PUSH AX
- LODSW ;PICK UP DIMENSIONS
- MOV BX,AX ;BX = DIMENSIONS
- POP AX ;AX = LOCATION
- XOR DX,DX
- XCHG BH,DL
- MOV BP,BX ;BP = BOXWIDTH
- MOV BX,80
- XCHG AL,BL
- MUL AH ;AX = ROW * 80
- ADD AX,BX ;ADD ON COL
- ADD AX,AX ;DOUBLE FOR WORDS
- MOV DI,AX ;DI = OFFSET ON SCREEN
- L1: PUSH DI
- MOV CX,BP ;SET UP BOXWIDTH
- L2: MOV BX,ES:[DI] ;SWAP A WORD
- LODSW
- MOV W [SI-2],BX
- STOSW
- LOOP L2 ;DO A WHOLE LINE
- POP DI
- ADD DI,160 ;BUMP TO NEXT ROW
- DEC DX ;COUNT DOWN LINES
- JNZ L1
- POP AX,BP,DI,SI,DX,CX,BX
- RET
- #ENDIF
- ;╔════════════════╗
- ;║ PARSE ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Parse filename │
- ; │ DS:SI - pointer to ASCIIZ filename │
- ; │ o/p 5D-64 major name parsed │
- ; │ o/p 65-67 minor name parsed │
- ; │ -CF set if ambiguity involved │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@PARSE
- $PARSE: PUSH AX,SI,DI,ES,SI
- L1: POP AX ;ignore the old directory break
- PUSH SI ;this is new directory break
- L2: LODSB ;pick up a byte
- CMP AL,":" ;is it drive terminator?
- JZ L1 ;yes - set as directory break
- CMP AL,"\" ;is it a level terminator?
- JZ L1 ;yes - set as directory break
- CMP AL,0 ;is it the ASCIIZ terminator?
- JNZ L2 ;no - keep looking
- POP SI ;go back to last break
- MOV AX,02900 ;get FCB parse command
- MOV ES,DS ;align segments
- MOV DI,O PSPFCB1 ;point to FCB1
- INT 021
- PUSH AX ;set result..
- PUSHF ;..into flags
- POP ES,DI,SI,AX
- RET
- #ENDIF
- ;╔════════════════╗
- ;║ LENSTR ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Length of ASCIIZ string │
- ; │ input pointer DS:SI output CX │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@LENSTR
- $LENSTR: PUSH AX,SI
- XOR CX,CX ;clear counter
- M1: INC CX ;bump counter
- LODSB ;pick up one byte
- CMP AL,0 ;is it the ASCIIZ null?
- JNZ M1 ;no - repeat
- POP SI,AX
- RET
- #ENDIF
- ;╔════════════════╗
- ;║ SETPOS ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Set position as $$VIDPOS │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@SETPOS
- @@GETADR = 1
- $SETPOS:PUSH AX,BX,DX
- MOV BH,B $$VIDPAGE
- MOV AH,02
- MOV DX,W $$VIDPOS
- INT 010
- POP DX,BX,AX
- JMPS $GETADR
- #ENDIF
- ;╔════════════════╗
- ;║ SETPAGE ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Set page as $$VIDPAGE │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@SETPAGE
- @@GETPAGE = 1
- $SETPAGE:
- PUSH AX
- MOV AL,B $$VIDPAGE
- INT 010
- POP AX
- ; (fall through)
- #ENDIF
- ;╔════════════════╗
- ;║ GETPAGE ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Establish Video mode and addresses │
- ; │ │
- ; │ output: ES:DI --> $$VIDSEG, $$VIDADR │
- ; │ $$VIDMODE - current mode │
- ; │ $$VIDCOLS - number of cols in this mode │
- ; │ $$VIDPAGE - current active page │
- ; │ $$VIDSHAPE - cursor shape │
- ; │ $$VIDPOS - [$VIDROW, $VIDCOL] │
- ; │ CF if not correct mode │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@GETPAGE
- @@GETPOS = 1
- $GETPAGE:PUSH AX,BX
- MOV AH,0F
- INT 010
- XOR BX,BX ;clear BX
- MOV B $$VIDPAGE,BH ;store page
- MOV W $$VIDMODE,AX ;store mode & $$VIDCOLS
- CMP B $$VIDCOLS,80 ;is the rowlength = 80 ?
- IF NZ SHR BX,1 ;if not, shift the length
- ADD BH,0B0 ;add on for the segment
- CMP AL,07 ;is it MDA text?
- JZ >L1 ;yes - jump
- ADD BH,08 ;go higher in memory
- CMP AL,04 ;is mode 00-03 ?
- CMC ;change response
- L1: POP BX,AX
- JC RET
- ; (fall through)
- #ENDIF
- ;╔════════════════╗
- ;║ GETPOS ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Get $$VIDPOS and $$VIDADR, ES:DI │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@GETPOS
- @@POS2ADR = 1
- $GETPOS:PUSH AX,BX,CX,DX
- MOV BH,B $$VIDPAGE
- MOV AH,03
- INT 010
- MOV W $$VIDSHAPE,CX
- MOV W $$VIDPOS,DX
- MOV AX,DX
- CALL $POS2ADR
- MOV W $$VIDADR,DI
- POP DX,CX,BX,AX
- RET
- #ENDIF
- ;╔════════════════╗
- ;║ POS2ADR ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ Convert row/col AH/AL to offset DI │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@POS2ADR
- @@VIDDATA = 1
- $POS2ADR:PUSH AX,BX
- MOV BX,AX
- MOV BH,0
- MOV AL,AH
- MUL B $$VIDCOLS ;calculate displacement
- ADD AX,BX ;add column number
- MOV ES,W $$VIDSEG ;set video segment
- MOV DI,AX ;set in DI
- CLC ;prevent carry
- POP BX,AX
- RET
- #ENDIF
- ;╔════════════════╗
- ;║ VIDDATA ╟─────────────────────────────────────────────┐
- ;╚╤═══════════════╝ VIDEO DATA (called by several routines) │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@VIDDATA
- $$VIDMODE DB 0 ;mode
- $$VIDCOLS DB 0 ;width of screen (columns)
- $$VIDPAGE DB 0 ;current page
- $$VIDSHAPE DW 0 ;shape of cursor
- $$VIDPOS DW ;cursor position
- $$VIDCOL DB 0 ;column
- $$VIDROW DB 0 ;row
- $$VIDADR DW 0 ;address (for DI)
- $$VIDSEG DW 0 ;segment (for ES)
- #ENDIF
- ;╔════════════════╗
- ;║ CRLF ╟─────────────────────────────────────────────┐
- ;║ NLPRINT ║ CRLF : print CR/LF only │
- ;║ PRINT ║ NLPRINT : print new line + message (DS:DX) │
- ;╚════════════════╝ PRINT : print message (DS:DX) │
- ; │ << NULL terminates a message >> │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@CRLF
- $CRLF: PUSH DX
- MOV DX,O CARRET + 2
- NLPRINT
- POP DX
- RET
- #ENDIF
- #IF @@NLPRINT
- $NLPRINT:PUSH DX
- MOV DX,O CARRET
- PRINT
- POP DX
- #ENDIF
- #IF @@PRINT
- $PRINT: PUSH AX,SI,DX
- XCHG DX,SI
- MOV AH,02
- L1: LODSB
- MOV DL,AL
- OR AL,AL
- JZ >L2
- INT 021
- JMPS L1
- L2: POP DX,SI,AX
- RET
- #ENDIF
- ;╔════════════════╗
- ;║ RESIGN ╟─────────────────────────────────────────────┐
- ;║ ABORT ║ Exit program: RESIGN: (ERRORLEVEL = 00) │
- ;╚╤═══════════════╝ ABORT : (ERRORLEVEL = AL) │
- ; │ │
- ; └─────────────────────────────────────────────────────────────┘
- #IF @@RESIGN
- @@ABORT = 1
- $RESIGN: XOR AL,AL
- #ENDIF
- #IF @@ABORT
- $ABORT: MOV AH,04C
- INT 021
- #ENDIF