FCB EQU 5CH ;default file ctrl block BDOS EQU 5 ;bdos jump point DIVERT1 EQU 1D78H ;diversion from ws console i/p routine INISUB EQU 287H PATCHSP EQU 2CBH ;wordstar free patch area LF EQU 0AH CR EQU 0DH ; ORG 100H JMP START ; MSG1 DB 1AH,'WSPATCH REV. 1.1',CR,LF DB 'INSTALLATION PROGRAM FOR WORDSTAR ' DB 'PATCHES: ',CR,LF DB '-BLINKING CURSOR',CR,LF DB '-ARROW KEY REDEFINITION',CR,LF DB 'FOR OSBORNE CP/M 2.2A-00F ' DB '& WORDSTAR VERSION 3.3 ',CR,LF DB LF,LF,'ENTER DESIRED BLINK RATE (0 TO 9)',CR,LF DB '0 IS VERY FAST, 9 IS VERY SLOW',CR,LF DB CR,LF,LF,'BLINK RATE? $' ; MSG2 DB CR,LF,LF,'**** MODIFICATIONS COMPLETED ' DB 'SUCCESSFULLY ****',CR,LF DB '$' ; ;BODY OF PATCHES LOCATED HERE ; ORG PATCHSP PATCHST ;* * * * CURSOR BLINK ROUTINE ; PATCH1 CPI 06H ;is this an i/p from console call? JNZ RETRN1 ;no, return to ws PUSH H TIMSET LXI D,$-$ ;blink rate timer ;(filled in by install routine) LOOP3 PUSH D CALL $-$ ;BIOS call to get cons status ;(filled in by install routine) POP D ORA A JNZ RETRN2 ;return to ws if char. ready DCR E JNZ LOOP3 DCR D JNZ LOOP3 ;decr. timer & loop until ready LHLD 0EF5AH ;get BIOS cursor pointer MOV A,M XRI 80H ;toggle cursor (underline on/off) MOV M,A JMP TIMSET ;restart timer ; RETRN2 LHLD 0EF5AH ;cursor pointer MOV A,M ORI 80H ;turn on cursor before leaving MOV M,A POP H MVI A,06 ;restore 'A' contents RETRN1 CALL 1777H ;ws inst. that diversion replaced RET ; ;* * * * ARROW KEY REDEFINITION ROUTINE ; PATCH2 LHLD $-$ ;BIOS arrow key def'n pointer ;(filled in by install routine) MVI M,05H ;^E INX H MVI M,04H ;^D INX H MVI M,18H ;^X INX H MVI M,13H ;^S RET ; ;FOLLOWING PATCH RESETS CP/M ARROW KEYS ; PATCH3 LHLD $-$ ;(filled in by install routine) MVI M,0BH ;^K INX H MVI M,0CH ;^L INX H MVI M,0AH ;^J INX H MVI M,08H ;^H RET PATCHND ;END OF BODY OF PATCHES ; ;START OF PATCH INSERTION ROUTINE ; ;* * * * CALCULATE AND INSERT BIOS ADDRESSES START LHLD 0001 ;get BIOS start address MVI L,7FH ;offset to arrow key pointer SHLD PATCH2+1 ;insert into patch SHLD PATCH3+1 MVI L,06H ;offset to get console status call SHLD LOOP3+2 ;insert into patch ; ;* * * * CHECK VALIDITY OF FILENAME LXI SP,STACK ;local stack LDA FCB+1 ;filename given? CPI 20H JNZ ONEFILE ;yes: ok ; MVI C,9 LXI D,ERR5 ;'NO FILE' message to console CALL BDOS JMP EXIT ; ONEFILE LDA FCB+17 ;2 filenames given? CPI 20H JZ GOODFIL ;no: ok ; MVI C,9 LXI D,ERR6 ;'TWO FILENAME' message to console CALL BDOS JMP EXIT ; GOODFIL MVI C,9 LXI D,MSG1 ;header message to console CALL BDOS ; RETRY1 MVI C,1 CALL BDOS ;input blink rate (1 digit, 0 to 9) CPI 03H ;^C? JZ EXIT ;yes: abort CPI 30H ;less than ascii zero? JP CHECK1 ;no: ok ; CHERROR MVI C,9 LXI D,ERR1 ;value error message to console CALL BDOS JMP RETRY1 ; CHECK1 CPI 3AH ;greater than ascii 9 ? JP CHERROR ;yes: error SUI 30H ;convert to BCD INR A ;+1 STA TIMSET+2 ;imbed value in patch1 ; MVI C,0DH ;reset disk drives CALL BDOS ; LXI D,FCB MVI C,0FH ;try to open ws file CALL BDOS INR A ;FF becomes 0 = error JNZ FILEOK ;if no error ; NOFILE MVI C,9 LXI D,ERR2 ;'FILE NOT FOUND' msg to console CALL BDOS JMP EXIT ; ;* * * * READ WORDSTAR INTO CORE ; FILEOK LXI H,1000H ;read buffer base adrs LOOP1 SHLD DMAADRS ;save it ; MVI A,H CPI 0B0H ;read buffer overflow (over B000h) JNZ NOFLOW ;no: ok ; MVI C,9 LXI D,ERR3 ;'OVERFLOW ERROR' msg to console CALL BDOS JMP EXIT ; NOFLOW XCHG MVI C,1AH ;call to set DMA adrs CALL BDOS ; MVI C,14H LXI D,FCB ;read a record into read buffer CALL BDOS ; ORA A ;end of file? JNZ INSERT ;yes: insert patches ; LHLD DMAADRS LXI D,128 DAD D ;inc DMA adr by 128 bytes JMP LOOP1 ;read next record ; ;* * * * INSERT DIVERSION FOR PATCH1 (BLINK) ; INSERT LXI D,0F00H ;mod bias (100H = 1000H) LXI H,DIVERT1 ;diversion from ws to patch1 DAD D ;+bias DCX H ;test for correct version of ws - MOV A,M ;check instruction before ;diversion location CPI 00 JZ CHECK2 ;same version: ok ; VERSERR MVI C,9 LXI D,ERR4 ;'VERSION ERR' msg to console CALL BDOS JMP EXIT ; CHECK2 DCX H MOV A,M CPI 01 ;check another byte to be sure JNZ VERSERR ;if error ; INX H INX H INX H LXI B,PATCH1 ;patch start adrs MOV M,C ;insert into ws INX H MOV M,B ; ;* * * * INSERT DIVERSION TO PATCH2 ; LXI H,INISUB ;diversion to patch2 DAD D ;+bias MVI M,0C3H ;store jmp at inisub INX H LXI B,PATCH2 ;patch2 start adrs MOV M,C ;insert into ws INX H MOV M,B INX H MVI M,0C3H ;store jmp at unisub = inisub+3 INX H LXI B,PATCH3 ;patch3 start adrs MOV M,C ;insert into ws INX H MOV M,B ; ;* * * * INSERT BODY OF PATCHES INTO WS FREE PATCH AREA LXI H,PATCHSP ;destination adrs DAD D ;+bias XCHG LXI H,PATCHSP ;source adrs LXI B,PATCHND-PATCHST ;byte count ;byte count above must be 124 (7C hex) ; DB 0EDH,0B0H ;Z80 'LDIR' block move inst ; ;* * * * PREPARE TO WRITE WORDSTAR BACK TO DISK LXI H,0100H ;reset FCB SHLD FCB+14 LXI H,0000 SHLD FCB+12 SHLD FCB+32 SHLD FCB+34 ; MVI C,0FH LXI D,FCB ;reset wordstar file CALL BDOS INR A ;FF becomes 0 = error JZ NOFILE ; LXI H,1000H ;write buffer st adrs SHLD WRTADRS XCHG ; LOOP2 MVI C,1AH ;call to set DMA CALL BDOS ; MVI C,15H LXI D,FCB ;write one record to disk CALL BDOS ; LHLD WRTADRS LXI D,128 DAD D ;inc DMA adr by 128 bytes SHLD WRTADRS XCHG LHLD DMAADRS ;if wrtadrs = end of read bfr, ;then all done MOV A,L CMP E JNZ LOOP2 ;if not equal: continue MOV A,H CMP D JNZ LOOP2 ;if not equal: continue ; MVI C,10H LXI D,FCB ;close file CALL BDOS ; MVI C,9 LXI D,MSG2 ; 'TERMINATION MSG' to console CALL BDOS ; EXIT JMP 0000 ;cp/m warm start entry ; ;* * * * STORAGE AND MESSAGES ; DMAADRS DW 0 ;read bfr pointer WRTADRS DW 0 ;write bfr pointer ; ERR1 DB 08H,'WRONG! ',8,8,8,8,8,8,8,8,'$' ERR2 DB CR,LF,LF,'ERROR: FILE NOT FOUND.' DB 'RESTART AND TRY AGAIN!',CR,LF,'$' ERR3 DB CR,LF,LF,'ERROR: READ BUFFER OVERFLOW. ' DB 'BAD SOURCE FILE?',CR,LF,'$' ERR4 DB CR,LF,LF,'ERROR: WORDSTAR FILE CORRUPT OR ' DB 'VERSION IS DIFFERENT',CR,LF,'FROM VERSION ' DB 'EXPECTED BY PATCH (SEE ABOVE)',CR,LF,'$' ERR5 DB 1AH,'WSPATCH REV 1.1',CR,LF DB 'ERROR: WORDSTAR FILENAME.EXT AND SOURCE ' DB 'DRIVE MUST',CR,LF DB 'BE SPECIFIED IN COMMAND LINE. -EG: ',CR,LF DB ' ',1BH,6CH,'WSPATCH B:WS.COM',1BH,6DH DB ' --TRY AGAIN!',CR,LF,'$' ERR6 DB 1AH,'WSPATCH REV 1.1',CR,LF DB 'ERROR: TWO FILENAMES GIVEN IN COMMAND LINE.' DB CR,LF,'SOURCE FILE MUST BE SAME AS DESTINATION' DB 'FILE.',CR,LF,' --TRY AGAIN!',CR,LF,'$' ; DS 64 STACK END