; WSLOAD ------------------------ A WordStar Utility ; ; This utility is described fully in WSLOAD.DOC within the library. ; The source code here is included in the event that you need to reset ; the OFFSET variable to a higher address. The code below will ; assemble correctly with either MicroSoft's M80 or with the fine ; public domain assmebler Z80MR. If you have problems or need special ; assistance, I will be glad to do what I can. Please send a SAS ; envelope and/or disk. ; ; Lindsay Haisley ; 14206 Spreading Oaks ; Leander, TX 78641 ; ; ; **** THE OFFSET VARIABLE: ; -------------------------- ; ; The offset variable below is the address of the end of your current ; version of WordStar. The is usually 4600 hex but if the area beyond ; this address is already in use for an initialization routine, you must ; find an area of free memory above this routine for WSLOAD to use. ; ; WSLOAD will give you a "MORPAT OVERLAY" error if an init routine ; already occupies the area above the current value of the offset. You ; must use DDT, Z8E, ZSID or some similar utility to find a string of ; null or unused bytes above the offset address and reset "offset" to ; the address of this string. You may need to load WordStar and SAVE a ; page or two more than the usual 70. Make sure you have 200 bytes of ; free space available for WSLOAD to occupy. offset equ 4600h ; ----------------------------------------------------------------------- aseg .z80 ; IGNORE THIS ERROR WITH Z80MR ; WordStar user patch area equates inisub equ 0287h morpat equ 02CBh fnwscm equ 0400h loadpt equ 1100h ; Address of WordStar in memory for this prog. loadref equ loadpt-100h ; CODE STARTS HERE org 100h jp ustart fcb1: defb 0,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,0,0,0,0 defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 fcb2: defb 0,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,0,0,0,0 defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 fcb3: defb 0,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,0,0,0,0 defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 cflag: defb '+' defb 0 fnbuf: defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0 endbuf: defb 0 getmsg: defb 0dh,0ah,'Enter the filename of your version of WordStar => ',0 outmsg: defb 0dh,0ah,'Enter the name you want for WordStar with WSLOAD' defb ' installed => ',0 csmsg1: defb 0dh,0ah,'Enter the character you want to preceed overlay ' defb 'filenames => ',0 csmsg2: defb 0dh,0ah,0ah,'All configuration overlays (except ' defb 'the default) must start with ''' defb 0 csmsg3: defb '''',0dh,0ah,0 e1msg: defb 0dh,0ah,'File ',0 e2msg: defb ' not found',0dh,0ah,0 dnmsg: defb 0dh,0ah,'Modified WordStar written to disk as ',0 mpemsg: defb 0dh,0ah,'MORPAT ERROR - Reset patch location',0dh,0ah,0 cremsg: defb 0dh,0ah,'Out of directory space. Can''t create output file.' defb 0dh,0ah,0 wremsg: defb 0dh,0ah,'Disk full. Operation aborted.',0dh,0ah,0 defmsg: defb 0dh,0ah,'Enter the default configuration filename => ',0 bktxt: defb 08h,20h,08h,0 nline: defb 0dh,0ah,0 ; PROGRAM STARTS HERE ustart: ld de,getmsg ; Ask for filename call zprt call getname cp 03h jp z,0000 ld a,(fnbuf) or a ret z ; Return to system if none given ld hl,fcb1 call xfer ld c,0fh ; Now open the file, if possible ld de,fcb1 call 5 inc a jr nz,ffound ld de,e1msg ; If no find, report and quit call zprt ld de,fcb1 call fnshow ld de,e2msg call zprt ret ; No Wordstar, no work !! (I quit!) ffound: ld hl,fcb1 ; Save open fcb for output if necessary ld de,fcb3 ld bc,24h ldir ld de,loadpt ; Read the input file to memory call readfile push hl ; Save size of file ld de,outmsg ; Get name of output file call zprt call getname cp 03h jp z,0000 ld hl,fcb2 call xfer ld de,fcb1 ; Is input same as output ld hl,fcb2 call namecmp jr z,same ld a,(fcb2+1) ; Or is no filename specified cp 20h jr nz,notsme same: ld hl,fcb3 ; Restore FCB opened for input to output FCB ld de,fcb2 ld bc,24h ldir jr creok notsme: ld c,13h ; Erase any file of similar name ld de,fcb2 call 5 ld c,16h ; Create the file ld de,fcb2 call 5 inc a jr nz,creok ; If directory full, say so and quit pop de ld de,cremsg call zprt ret creok: ld de,defmsg ; Get the default config. filename call zprt call getname cp 03h jp z,0000 ld hl,dnme call xfer getflg: ld de,csmsg1 ; Get the flag character call zprt ld c,01 call 5 call upcase cp 0dh jr z,ffdef ; If none given, use default cp 21h ; Don't accept control characters jr nc,ffok call bell jp getflg ffok: ld (cflag),a ; Tell about the flag ffdef: ld de,csmsg2 call zprt ld de,cflag call zprt ld de,csmsg3 call zprt ; ACTUAL MODS TO WORDSTAR START HERE ld a,(inisub+loadref) cp 0c3h ; See if JP instruction in INISUB jr nz,okini ld hl,(inisub+loadref+1) ; If so, see where it JP's to and a ld de,offset sbc hl,de jp c,morpok ld de,mpemsg call zprt pop de ret ; If inisub too hi, quit okini: ld a,0c3h ; Put a JP in inisub ld (inisub+loadref),a ld a,0c9h ; RETurn instruction instead of a JP to MORPAT ld (retins),a ; morpok: add hl,de ld de,offset ld (inisub+loadref+1),de ; Set up a patch and return situation ld (retad),hl ld a,(cflag) ; Enter the flag character into the overlay ld (f1+1),a ld (f2+1),a ld hl,fcb2 ; Save the filename for later use by WordStar ld de,nme ld bc,12 ldir ; Now move the working code into WordStar image ld hl,patstrt ld de,loadref+offset ld bc,patend-patstrt ldir ; Now write the image back to a file ld de,loadpt pop bc call writfile ; Write the file jr z,alldn ld de,fcb2 ld c,13h call 5 ld de,wremsg ; If error, say so call zprt ret ; All done, so say so and quit alldn: ld de,dnmsg call zprt ld de,fcb2 call fnshow ld de,nline call zprt ret ; ++++++++++++++++++++++++ SUBROUTINES ++++++++++++++++++++++++++ getname: ; Get a valid CP/M filename to fnbuf xor a ; Zero fnbuf ld hl,fnbuf ld de,fnbuf+1 ld (hl),a ld bc,11 ldir ld hl,fnbuf fnloop: ld de,06 ; Use BIOS to fetch character call ubios cp 03h ret z cp 0dh ; Check for CR to mark end of string jr nz,morget ld (hl),0 ld de,nline ; If end, go on call zprt ret morget: call upcase ; Convert to Upper case, if approp. jr c,okchar ; If conversion done, character must be OK cp 7fh ; Is it a DEL jr z,bsordl cp 08h ; Or is it a BS jr nz,notbs bsordl: ld de,fnbuf ; Ignore if start of buffer and a push hl sbc hl,de pop hl jr z,fnloop dec hl ld de,bktxt push hl call zprt pop hl jr fnloop notbs: cp 21h ; Don't accept other control characters jr c,fnloop okchar: ld de,endbuf ; Check to see if end of buffer reached and a push hl sbc hl,de pop hl jr c,sizok call bell jr fnloop sizok: ld (hl),a inc hl ld c,a ld de,09h call ubios jr fnloop ; -------------------------------------------------------------- xfer: ; Transfer filename in FNBUF to (hl) in FCB format push hl xor a ; Clean and prep area to recieve transfer ld (dotflg),a ld (hl),a ; 0 for disk inc hl ld (hl),20h push hl pop de inc de ld bc,10 ldir pop hl ld de,fnbuf ; Do disk desig, if there is one ld a,(fnbuf+1) cp ':' jr nz,nodisk ld a,(de) sub 40h ld (hl),a inc de inc de nodisk: inc hl ld b,8 xlup: ld a,(de) ; Then copy characters or a ret z cp '.' ; Check for a dot jr nz,nodot ld a,(dotflg) ; Make sure only one dot or a ret nz dec a ld (dotflg),a inc de ld c,b ; Set to copy extent, if any ld b,0 add hl,bc ld b,3 nodot: ld a,b or a jr z,lulu ld a,(de) ld (hl),a dec b inc hl lulu: inc de jr xlup dotflg: defb 00 ; Flag to prevent multiple dots in name ; --------------------------------------------------------------- readfile: ; Load file spec in FCB1 to mem starting at (de) ; Return number of sectors loaded in hl ld bc,00 rloop: push de push bc ; Save sector counter ld c,1ah call 5 ; Set DMA as per reg de ld c,14h ld de,fcb1 call 5 ; Read a Sector pop bc pop de or a jr nz,lfdone ld hl,80h ; Bump the DMA pointer add hl,de ex de,hl inc bc ; Bump the sector counter jr rloop ; Go back for more lfdone: ld h,b ld l,c ret ; -------------------------------------------------------------------- writfile: ; Writes (bc) sectors from memory, starting at (de) to ; the file spec in FCB2. Closes the file when done. ld a,c or b jr z,wfdone ; Check up on the sector count push de push bc ; Set the DMA ld c,1ah call 5 ld c,15h ; Write a record ld de,fcb2 call 5 pop bc pop de and a ret nz ld hl,80h ; Bump the DMA pointer add hl,de ex de,hl dec bc jr writfile wfdone: ld c,10h ; Close the file ld de,fcb2 call 5 xor a ret ; -------------------------------------------------------------------- namecmp: ; Compares two names in FCB (12) bytes. Returns zflg ; according to results of compare ld b,12 cmplup: ld a,(de) cp (hl) ret nz inc de inc hl dec b jr nz,cmplup ret ; -------------------------------------------------------------------- ubios: push hl ; Use a BIOS direct call. Save hl reg. ld hl,(001) ; de contains offset from BIOS start add hl,de ld (bi1),hl bi1 equ $+1 call 0000 ; Self mod code pop hl ret ; --------------------------------------------------------------------- zprt: ld a,(de) ; print null term string or a ret z push de ld c,2 ld e,a call 5 pop de inc de jr zprt ; --------------------------------------------------------------------- fnshow: ; Show a file name in *.* format from FCB format (in de) ex de,hl ld a,(hl) cp 0 jp z,nfndsk add a,40h push hl ld e,a ld c,2 call 5 ld e,':' ld c,2 call 5 pop hl nfndsk: inc hl ld b,8 call nfnlup doext: ld c,b ld b,0 add hl,bc ld a,(hl) cp 20h ret z ld e,'.' ld c,2 push hl call 5 pop hl ld b,3 call nfnlup ret nfnlup: ld e,(hl) ld a,20h cp e ret z push bc push hl ld c,2 call 5 pop hl pop bc inc hl dec b jr nz,nfnlup ret ; --------------------------------------------------------------------- upcase: cp 61h ; Convert to upper case jr c,notlo cp 7bh ret nc and 01011111b ; If it is, uppercase it and a notlo: ccf ret ; --------------------------------------------------------------------- bell: push hl ; Ring the bell !! ld c,02 ld e,07 call 5 pop hl ret ; ---------------------------------------------------- ; THE FOLLOWING IS THE PATCH TO THE END OF WORDSTAR ; ---------------------------------------------------- patstrt equ $ ld hl,05dh ; find an argument, if any ld a,(hl) f1: cp 0 jr z,isarg-offset+patstrt ld hl,06dh ld a,(hl) f2: cp 0 jr z,isarg-offset+patstrt jr godef-offset+patstrt ; if none, try for the default fnme isarg equ $+offset-patstrt dec hl push hl ld de,fcb ; move the filename to the fcb ld bc,12 ldir pop de ld a,e cp 05ch ; If first arg, substitute second arg jr nz,nomove-offset+patstrt ld hl,06ch ld bc,12 ldir nomove equ $+offset-patstrt call open ; open the file jr nz,pgodef-offset+patstrt godef equ $+offset-patstrt ; If not found, try the default fnme ld hl,defnme ld de,fcb ld bc,12 ldir call open jr z,jrret-offset+patstrt ; Can't find anything, so just do WS pgodef equ $+offset-patstrt ld de,80h ; Get set to loop push de lloop equ $+offset-patstrt pop hl ld de,80h add hl,de ex de,hl push de ld c,1ah call 5 ; Advance DMA by 80h bytes ld c,14h ld de,fcb call 5 ; Read a Sector or a jr z,lloop-offset+patstrt ; Until no more to read pop de ld de,80h ; Restore DMA ld c,1ah call 5 ld de,fnwscm ; Move the filename into WordStar ld hl,wsname ld bc,12 ldir retins equ $ jrret equ $+offset-patstrt jp 0000 retad equ $-2 open equ $+offset-patstrt ld c,0fh ld de,fcb call 5 inc a ret fcb equ $+offset-patstrt defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 wsname equ $+offset-patstrt nme: defb 0,0,0,0,0,0,0,0,0,0,0,0 defb 0 defnme equ $+offset-patstrt dnme: defb 0,' ' defb 0 patend equ $ end