; Overlay to WS4.0 R.Gaspari 12-12-87 ; Assemble with Z80MR. Overlay onto WS with DDT. PROGEND EQU 1E00h ; original end of the program being modified KBA EQU 0D700H ; base addr below which code is loaded (ccp) KKS EQU 200H ; how far below kba code will go NO EQU 0 YES EQU .NOT.NO NSADV EQU YES ; using Northstar Advantage? @N ; (for on-screen BOLD and UNDERLINE) SMTCLK EQU YES ; using SMT no-slot clock? @S ; (for pop-up clock display) Z80DOS EQU YES ; using Z80DOS? @Z ; (to trap make-file bdos calls) ORG 0100h ; overlay the program being modified JP LOADCD ; (WS had a JMP 1A1F here) if nsadv ; @N1 ; ************************************************* ; PART I - VIDATT CODE INSIDE WORDSTAR ; ************************************************* USORG EQU 0F400H ; start of USER.ASM (F400 for floppy) ORG 03C1H ; my code for video attributes VIDATT: LD A,C ; get the attr into A OR A ; see if zero JR NZ,VSET ; if non-zero, then skip reset LD HL,USORG+203H ; RESET ROUTINE LD (USORG+10),HL ; this resets CONSOUT in bios LD C,2 ; this resets inverse video LD E,2 ; output a ^B character (02h) CALL 5 RET ; return from VIDATT after reset VSET: AND 01111000B ; see if bits 3,4,5,6 are set JR Z,VMRK ; if not, do the "mark" ; otherwise, do the "repl" VREP: ; replace bios conout RES 2,A ; don't mark (inverse vid) LD (HCONF),A ; save the VIDATT status byte LD HL,VCONO ; get addr of replacement conout LD (USORG+10),HL ; point CONOUT to my new code RET ; return from VIDATT VMRK: ; mark with inverse video LD C,2 LD E,1 ; output ^A (01h) to set inv video CALL 5 RET ; return from VIDATT ; ; PART Ia - REPLACEMENT CONOUT ROUTINE ; ; note that as much as possible is here ; in low memory, only the absolute necessity ; is placed in high mem where room is scarce. VCONO: CALL USORG+203H ; first do the conout we replaced LD A,(HCONF) ; then get the status byte OR A ; if high mem status byte is zero RET Z ; then return LD HL,(USORG+21EH) ; otherwise get addr of current cursor LD B,H LD H,L LD L,B ; invert H and L DEC H ; point back at char we just sent out BIT 5,A ; see if superscript JR Z,VNS ; if not, skip this RES 4,A ; if yes, turn off subsc LD (HCONF),A VNS: LD D,10 ; 10 is a commonly used constant JP HCONO ; & go to high mem to modify it VREF EQU $ ; VIDATT must end before 0441h endif ; @N1 ; ************************************************************* ; PART II - WORDSTAR INITIAL START-UP DEFAULTS ; ************************************************************* ORG 0446h ; length of long delay (at start-up)? DW 400 ; about one/half second (was 2000) ORG 080Ch ; page number printed? DB 0 ; not at start-up ORG 083Bh ; help level at start-up? DB 2 ; set to 2 ORG 086Ch ; VIDATT attribute for ruler line? DB 2 ; (bit 2 = inverse video) ORG 0857h ; "Insert" on or off at start-up? DB 0 ; OFF ORG 0858h ; Print controls shown at start (^O^D)? DB 0 ; NO if nsadv ; @N2 ORG 0380h ; code for cursor ON JP 045Bh ; (manual says this is faster) ORG 0383h ; code for cursor OFF JP 0463h ; (after cursor ON patch) ORG 045Bh ; start of MORPAT user patch area LD C,2 ; code for cursor ON LD E,18H ; ^X for cursor ON CALL 5 RET LD C,2 ; code for cursor OFF LD E,19H ; ^Y for cursor OFF CALL 5 RET endif ; @N2 ; ************************************* ; PART III - FUNCT KEY PROC ; ************************************* ORG PROGEND ; point to end of normal WS LOADCD: LD HL,0 ; * prevent soft return to CCP EX (SP),HL ; * any soft retn becomes JP 0 CALL SETUP ; load CCP and BIOS overlays JP 1A1FH ; continue with original program ; ; PART IIIa - SETUP JUMP VECTORS ; M6 EQU -6 ; a constant SETUP: if nsadv.and.smtclk ; @N3 @S1 LD DE,USORG ; spot in BIOS to put clock code LD HL,UCODE ; point to data we'll put there LD BC,USIZE ; size of code block to be moved LDIR endif ; @N3 @S1 LD HL,(6) ; get bdos vector DF06 LD (KREM6),HL ; store it for future use LD DE,M6 ; get -6 ADD HL,DE ; HL now has DF00 (source) LD DE,KBA-KKS ; DE now has D300 (destination) LD BC,9 ; move 9 bytes LDIR LD HL,(1) ; get warm boot vector ED03 (source) LD DE,KBA-KKS+9 ; DE now has D309 (destination) LD BC,12 ; move 12 bytes LDIR LD DE,KBA-KKS+21 ; DE has D315 (destination) LD HL,KKODE+21 ; HL points to code below LD BC,KSIZE ; move bytes LDIR LD HL,KBDOS ; get new bdos vector LD (6),HL ; put it in place LD HL,(1) ; point to actual table (dest) LD DE,KBOOT ; point to replace table (source) EX DE,HL ; LD BC,12 ; move 12 bytes LDIR if z80dos ; @Z1 LD HL,(KBA-KKS+7) LD (Z8ENTRY+1),HL LD HL,Z8NEW LD (KBA-KKS+7),HL endif ; @Z1 RET ; done with SETUP ; ****************************************************************** ; PART IV - NEW FNCT KEY VECTOR CODE (relocated to high mem) ; ****************************************************************** KKODE: OK EQU (KBA-KKS)-KKODE ; offset KSER EQU $+OK DS 6 ; space for serial number KBDOS EQU $+OK DS 3 ; space for bdos jump BBOOT EQU $+OK DS 3 ; orig warm boot jmp vector BSTAT EQU $+OK DS 3 ; orig console status BCONIN EQU $+OK DS 3 ; orig console input BCONOUT EQU $+OK DS 3 ; orig console output KBOOT EQU $+OK JP KBT ; new warm boot vector KCSTAT EQU $+OK JP KST ; new console status KCONIN EQU $+OK JP KIN ; new console input KCONOUT EQU $+OK JP BCONOUT ; new console output ; ****************************************** ; NEW WARM BOOT ROUTINE KBT EQU $+OK ; remove key code each wm boot CALL KREM ; put the 4 bios vectors back JP 0 ; reboot to cpm ccp KREM EQU $+OK LD HL,(KREM6) ; get orig bdos jmp vector LD (6),HL ; put it back LD DE,(1) ; point to ED03 LD HL,BBOOT ; get orig actual data LD BC,12 ; move 12 bytes LDIR XOR A RET ; ************************************** ; NEW CONSOLE STATUS ROUTINE KST EQU $+OK LD A,(KEYINF) OR A JP Z,BSTAT ; LD A,0FFH RET ; ******************************************* ; NEW CONSOLE CHARACTER INPUT ROUTINE KIN EQU $+OK LD HL,KEYINF ; get the counter of keys waiting LD A,(HL) OR A JR NZ,KEYWAT ; go process the keys waiting CALL BCONIN ; get the byte using actual bios CP 7FH ; see if it's a "delete" RET C ; if less than 7F, return with it JR NZ,KEYFNI ; if greater than 7F, prep for funct key LD A,(KEYDEL) ; if equal to 7F, replace with a ^H RET ; KEYFNI: CP 9EH ; see if it's CMND-F4 JR NZ,KEYNR ; if not, skip this stuff LD HL,KREMC ; look at the removal counter INC (HL) ; (2nd F4 removes fnct key code) LD A,(HL) AND 2 JP NZ,KBT ; if Z, go remove key code KEYNR: CP 9DH ; see if it's CMND-F3 JR NZ,KEYNP ; if not, skip this stuff LD A,(080CH) ; load the .pn page number print flag CPL ; complement the accumulator LD (080CH),A ; store the toggled flag KEYNP: LD B,A ; store the function key LD A,(KEYLEN) ; get length of replacement byte string OR A ; see if zero LD A,B ; get the function key back RET Z ; if len=0, don't process function keys KEYFN EQU $+OK CP 0DBH ; now see if its F1 - F15 or if a cursor JR NC,KEY2 ; if no carry, its greater (F1 - F15) SBC A,7FH ; subtract to point to offset in table LD HL,(KEYNMP) ; get address of the cursor replacements JR KEYX ; go to the exchange routine KEY2: SBC A,0DBH ; subtract to get the offset for our table LD HL,(KEYFNP) ; get address of the fn key replacements KEYX: LD C,A ; store offset temporarily in C LD A,(KEYLEN) ; get the length of each replacement str DEC A ; LD (KEYINF),A ; store the number of remaining bytes LD D,A ; the number of times to add A to itself LD A,C ; get the offset back from C KEYX2: ADD A,C ; by adding N times, adjust offset for DEC D ; the number of bytes in KEYLEN JR NZ,KEYX2 ; repeat till D=0 LD E,A ; put the offset in DE, prep for DAD D LD D,0 ; ditto ADD HL,DE ; HL now points to the replacement bytes LD D,(HL) ; get first replacement byte INC HL ; point to next byte LD (KEYPTR),HL ; store pointer to the next byte LD A,(HL) ; get next byte OR A JR NZ,KNXTZ ; if next byte NZ skip, otherwise... LD (KEYINF),A ; notify keyinf that there's no more KNXTZ: LD A,D ; get the replacement key back OR A ; check that it's not a null RET NZ ; if no null, return with it LD (KEYINF),A ; otherwise notify keyinf that no more RET ; return with function key replacement KEYWAT: DEC A ; decrement count of keys waiting LD (HL),A ; store for future use LD HL,(KEYPTR) ; get address of next byte waiting LD A,(HL) ; get the byte there INC HL ; update the pointer to the next byte LD (KEYPTR),HL ; and store it RET ; return with the byte that was waiting KREMC EQU $+OK DW 0 ; temp storage for CMND-F4 counter KEYPTR EQU $+OK DEFW 0 ; temp pointer to next replacement byte KEYINF EQU $+OK DEFB 0 ; temp storage for number of keys waiting KREM6 EQU $+OK DW 0 ; temp storage for orig bdos (DF06) KEYDEL EQU $+OK ; permanent storage for delete key DEFB 08H ; replacement (set delete = ^H) KEYLEN EQU $+OK ; permanent storage for length of DEFB 2 ; each replacement string KEYFNP EQU $+OK dw KFNTBL ; pointer to KFNTBL KEYNMP EQU $+OK dw KNMTBL ; pointer to KNMTBL ; ***************************************************** ; PART IVa - FUNCTION KEY REPLACEMENT DATA ; ***************************************************** KNMTBL EQU $+OK DEFB 0,0 ; 80h cmnd - DEFB 0,0 ; 81h cmnd . DEFB 05H,0 ; 82h up arrow DEFB 03H,0 ; 83h 3 arrow DEFB 1AH,0 ; 84h 1 arrow DEFB 11H,0 ; 85h 5 arrow (center) DEFB 04H,0 ; 86h rt arrow DEFB 17H,0 ; 87h 7 arrow DEFB 13H,0 ; 88h lf arrow DEFB 12H,0 ; 89h 9 arrow DEFB 18H,0 ; 8Ah dn arrow DEFB 0,0 ; 8Bh undefined DEFB 0,0 ; 8Ch cntl , DEFB 0,0 ; 8Dh SHFT ENTER DEFB 0,0 ; 8Eh cntl . DEFB 0,0 ; 8Fh cntl - DEFB 0,0 ; 90h cntl 0 DEFB 0,0 ; 91h cntl 1 arrow DEFB 0,0 ; 92h cntl 2 arrow DEFB 0,0 ; 93h cntl 3 arrow DEFB 01H,0 ; 94h cntl 4 arrow DEFB 11H,0 ; 95h cntl 5 arrow DEFB 06H,0 ; 96h cntl 6 arrow DEFB 0,0 ; 97h cntl 7 arrow DEFB 0,0 ; 98h cntl 8 arrow DEFB 0,0 ; 99h cntl 9 arrow DEFB 0,0 ; 9Ah cntl ENTER DEFB 0AH,09H ; 9Bh cmnd F1 DEFB 0AH,13H ; 9Ch cmnd F2 DEFB 0AH,06H ; 9Dh cmnd F3 DEFB 0AH,08H ; 9Eh cmnd F4 DEFB 0AH,02H ; 9Fh cmnd F5 DEFB 0AH,0DH ; A0h cmnd F6 KFNTBL EQU $+OK DEFB 0BH,04H ; F1 DEFB 0BH,13H ; F2 DEFB 10H,13H ; F3 DEFB 10H,02H ; F4 DEFB 15H,00H ; F5 DEFB 0FH,09H ; F6 DEFB 0FH,03H ; F7 DEFB 10H,0CH ; F8 DEFB 0BH,02H ; F9 DEFB 0BH,0BH ; F10 DEFB 0CH,00H ; F11 DEFB 10H,16H ; F12 DEFB 10H,14H ; F13 DEFB 16H,00H ; F14 DEFB 07H,00H ; F15 DEFB 0BH,11H ; SH-F1 DEFB 0BH,13H ; DEFB 0FH,0AH ; DEFB 0AH,00H ; DEFB 02H,00H ; DEFB 0FH,0EH ; DEFB 0FH,07H ; DEFB 0FH,00H ; DEFB 0BH,16H ; DEFB 0BH,03H ; DEFB 11H,06H ; DEFB 0FH,13H ; DEFB 0FH,04H ; DEFB 0EH,00H ; DEFB 19H,00H ; SH-F15 ; **************************************************** ; PART IVb - VIDEO PROC CODE FOR "FEATURES" ; **************************************************** M10 EQU -10 ; a constant HCONF EQU $+OK DB 0 HCONO EQU $+OK ; this code becomes HCONO after moved LD A,80H ; map video memory onto OUT (0A0H),A ; 0000h to 8000h LD A,81H OUT (0A1H),A LD A,(HCONF) ; get the status flag BIT 6,A ; see if bit 6 is set JR Z,NBOLD ; if zero, jmp to not bold LD C,D ; counter for the 10 bytes per char NXTM: ; ROUTINE TO MAKE BOLD LD A,(HL) ; get first byte of the char into A LD B,A ; put into B also RLA ; shift left the version in A OR B ; combine it with its image in B LD (HL),A ; & put it back in display memory INC HL ; point to next byte DEC C ; & continue JR NZ,NXTM LD BC,M10 ; put -10 into BC ADD HL,BC ; set HL to its orig value NBOLD: LD A,(HCONF) BIT 3,A ; see if bit 3 is set JR Z,NUNDR ; if zero, jmp to not undrline LD B,9 ; ROUTINE TO ADD UNDERLINE NXTU: INC L ; HL points to top of 10 bytes DEC B ; inc L to point to bottom byte JR NZ,NXTU ; point to last byte of char LD (HL),0FFH ; put a line (FF) into video memory LD BC,M10+1 ; Put -9 into BC ADD HL,BC ; reset L to its orig value NUNDR: LD A,(HCONF) BIT 5,A ; see if bit 5 set JR Z,NSUPR ; if not, jmp to not superscript LD C,D ; counter for 10 bytes of display NXTV: ; ROUTINE TO MAKE SUPERSCRIPT LD A,(HL) ; get top byte DEC L ; go up 3 rows DEC L DEC L LD (HL),A ; put data there INC L ; go down 4 rows INC L INC L INC L DEC C JR NZ,NXTV ; and repeat XOR A ; get a zero DEC L ; point to bottom byte LD (HL),A ; put zero there DEC L ; point to 2nd from bottom LD (HL),A ; put zero there DEC L ; point to 3rd from bottom LD (HL),A NSUPR: LD A,(HCONF) BIT 4,A ; see if subscript JR Z,NSUBS ; if not, jmp to not subscript LD C,D ; prepare to point to *bottom* byte VSR: INC L ; of the 10 byte char display DEC C JR NZ,VSR LD C,D ; counter for 10 bytes of display NXTT: ; ROUTINE TO MAKE SUBSCRIPT LD A,(HL) ; get the bottom byte INC L ; go down 2 rows INC L LD (HL),A ; put byte there DEC L ; go up 3 rows DEC L DEC L DEC C JR NZ,NXTT ; continue XOR A ; get a zero INC L ; point to top row LD (HL),A INC L ; point to row 2 LD (HL),A DEC L ; reset HL to top row NSUBS: LD A,1 ; reset to normal memory OUT (0A0H),A ; (remove display memory LD A,2 ; from 0000 to 8000h) OUT (0A1H),A RET ; return from VCONO ; (done with high memory) ; ********************************* ; PART IVc - Z80DOS TRAP ; ********************************* if z80dos ; @Z2 Z8NEW EQU $+OK LD A,C ; move bdos funct number into A CP 0FH ; see if it's the first open-file call JR Z,Z8GET ; if yes, GET the time stamp CP 16H ; see if this is make-file call JR Z,Z8USE ; if yes, USE the time stamp JR Z8ENTX ; all else, go do real bdos jump Z8GET: PUSH DE ; preserve the fcb for bdos 54 PUSH DE CALL Z8ENTRY ; go to bdos & return POP DE ; get the fcb back again PUSH AF ; preserve open-file bdos status INC A ; see if it's 0ffh (no file found) LD (Z8NFF),A ; store results for use later JR Z,Z8SKP ; if no file found, skip get stamp LD C,54 ; 54 = get stamp CALL 5 ; Z8SKP: POP AF ; get orig open-file status back POP DE ; and orig fcb RET Z8USE: LD A,(Z8NFF) ; see if open-file was successful OR A ; a=0 if unsuccessful JR Z,Z8ENTX ; if zero, skip use-stamp PUSH BC ; save bdos funct number (c=16h) PUSH DE ; save fcb LD C,55 ; 55 = use stamp CALL 5 POP DE POP BC Z8ENTRY EQU $+OK Z8ENTX: JP 0 ; do the JP into real bdos Z8NFF EQU $+OK DB 0 ; flag for no-file-found endif ; @Z2 KREF1 EQU $ ; location of end of code KREF2 EQU $+OK ; location of end (after it's moved) KSIZE EQU $-KKODE ; the size code to be moved IF (KSIZE).GT.(KKS) * ERROR - allow more size for KKS ENDIF ; ************************************************* ; PART V - BIOS CODE (moved to high memory) ; ************************************************* if nsadv.and.smtclk ; @N4 @S2 *include user201.azm ; see NOSLTDOS.LBR for more info endif ; @N4 @S2 end