ZRDOS EQU 0 ; Define operating system to be used: ; ; CP/M = 0 ; ; ZRDOS = 1 STNDALON EQU 0 ; Define installation technique: ; ; Inclusion in BIOS sysgen = 0 ; ; Stand-alone program = 1 PATCH EQU 0 BIOS EQU 0D300H BDOS EQU BIOS-0E00H CCP EQU BDOS-800H BUFFSIZ EQU 124 PAGE1LEN EQU 8 ; Define length of Morrow Page 1 data BIOSLOC EQU BIOS+100H+PAGE1LEN ; Define BIOS load point SYSGLOC EQU 2100H+100H+PAGE1LEN ; Define SYSGEN load point BDOSNTRY EQU 0005H LF EQU 0AH CR EQU 0DH IFTRUE STNDALON ; Then ORIGIN the image at SYSGEN location ORIGIN EQU SYSGLOC ; Origin at SYSGEN load point ORG 100H LD HL,NOTNABLD ; Set up for.. LD (MESSAGAD),HL ; .."error condition found" message LD HL,(TABLEPTR) ; Load the address of the POINTER TO the.. ; ; ..BDOS function table LD DE,10*2 ; Load offset into BDOS function table and.. ADD HL,DE ; ..add to address of the table EX DE,HL ; Save result in DE-regs LD HL,CPM3BFX ; Set pointer to word containing the original.. LD A,(HL) ; ..BDOS function routine, then test if.. SUB E ; ..the computed address is the same: JR NZ,DONTALOW ; If it is NOT, then.. INC HL LD A,(HL) SUB D JR NZ,DONTALOW ; ..don't allow the.. ; ; ..enabling routine to execute ; ; ; If the address is the same, then we have.. ; ; ..the correct DOS version, so do allow the.. ; ; ..enabling routine to execute CPM3BFIN: ; LD HL,ENABLED ; Set up for.. LD (MESSAGAD),HL ; .."All OK" message DONTALOW: LD DE,(MESSAGAD) LD C,9 CALL BDOSNTRY LD DE,BIOSLOC ; Set destination.. LD HL,SYSGLOC ; ..and source addresses LD BC,CODESIZE ; Set move length LDIR ; Move routine image into BIOS LD HL,BDOSTABL+(2*10) ; Insert BDOS patch point address at.. LD (BIOS+0FEH),HL ; ..BIOS page1 - two bytes JP 0 ; Exit to warm boot MESSAGAD DW 0 CPM3BFX DW BDOSTABL+(2*10) ; Address of pointer compared for validation NOTNABLD DB CR,LF,'System pointers don''t match, ' DB 'CPM+ style console buffer NOT ENABLED!!' DB '$' ENABLED DB CR,LF,'CPM+ (3.x) style console buffer ENABLED!!',CR,LF,LF DB '^W or ^R : Restores previous command',CR,LF DB '^A or ^S : Moves cursor LEFT one byte',CR,LF DB '^F or ^D : Moves cursor RIGHT one byte',CR,LF DB 'back-space: Deletes character to left of cursor',CR,LF DB 'Delete key: Deletes character to left of cursor',CR,LF DB '^G : Deletes character AT the cursor',CR,LF DB '^X : Deletes FROM cursor TO left end of line',CR,LF DB '^K : Deletes FROM cursor TO right end of line',CR,LF DB '^B : Moves cursor to start OR end of line (toggle)' DB CR,LF,LF DB ' enters line REGARDLESS of cursor position in line' DB CR,LF,LF DB 'If ^P sounds BELL, then printer ECHO is ENABLED!',CR,LF DB 'If ^P DOES NOT sound BELL, then printer ECHO is DISABLED!' DB CR,LF DB '$' ELSE ; else ORIGIN at actual BIOS location ORIGIN EQU BIOSLOC ; Origin at BIOS load point ENDIF ORG ORIGIN BIAS EQU BIOSLOC-ORIGIN ; Define the bias for absolute addresses ;=========================START OF BUFFER ROUTINE========================= ; ; Replacement for BDOS function 10 (Read Console Buffer) ; ; ; (Defines some symbols referencing locations within BDOS and BIOS) ; ; ; The BUFFADDR and BDOSTABL refer to locations within BDOS. ; These differ depending upon your CP/M revision level. ; ; (The tenth word in BDOSTABL (rel. to 0) is ; replaced by the CPM3BUFF entry address) ; ; See CPM3BUFF.DOC for treatise on how to find these addresses. ; ; SAVEAREA refers to a location within your BIOS where you can ; reserve some space to save the user's input image, so you can ; restore it. It may be any length up to 128 bytes. If you are ; cramped for space, then you can make it short, and CPM3BUFF will ; only use what you give him. He may only be able to restore the ; first 16 bytes of a long message, but that's better than nothing. ; ; IFTRUE ZRDOS BUFFADDR EQU BDOS+01AH ; Pointer to User's message buffer [ZRDOS] CTLPTOGL EQU BDOS+011H ; ^P toggle (echo screen to printer) [ZRDOS] BDOSTABL EQU BDOS+0D70H ; Pointer to BDOS function table. [ZRDOS] TABLEPTR EQU BDOS+0B7H ; Pointer to a POINTER to BDOS table. [ZRDOS] SAVEAREA EQU 0EB80H ; First byte of Buffer Image save area [ZRDOS] ELSE BUFFADDR EQU BDOS+343H ; Pointer to User's message buffer [CP/M] CTLPTOGL EQU BDOS+30DH ; ^P toggle (echo screen to printer) [CP/M] BDOSTABL EQU BDOS+0047H ; Pointer to BDOS function table. [CP/M] TABLEPTR EQU BDOS+0038H ; Pointer to a POINTER to BDOS table. [CP/M] SAVEAREA EQU 0FF00H ; First byte of Buffer Image save area [CP/M] ENDIF ; ; ; SAVEAREA may be changed to point to any.. ; ; ..free space controlled by BIOS, or made.. ; ; ..a DS and position appropriately ; ; ; The first byte of SAVEAREA contains the.. ; ; ..length of current "saved" buffer image ; ; ; NOTE: The Warm-Boot code that implements.. ; ; ..the CPM3BUFF routine MUST store a zero.. ; ; ..in SAVEAREA to prevent a spurious.. ; ; ..last-previous-message if the user.. ; ; ..does a ^W immediately after warm-boot ; ;BUFFADDR EQU WORKAREA ; Testbed EQU (delete when installing in BIOS) ; ;CTLPTOGL EQU WORKAREA+2 ; Testbed EQU (delete when installing in BIOS) ; ;SAVEAREA EQU WORKAREA+2 ; Testbed EQU (delete when installing in BIOS) ; ; SAVIMAGE EQU SAVEAREA+1 ; Define start of message image in save-area ; ; The next symbol represents the end of the buffer save area. It must ; always immediately follow the SAVEAREA definition statement. ; SAVEEND EQU SAVEAREA+(BUFFSIZ+1) ; ; ; The next symbol defines the number of bytes of the user's ; input to be saved for recovery via the ^W function (restore ; last previous input line). This value can be anything from ; 1 to 255. If the user enters an input line longer than the ; save area, only the first SAVESIZE bytes will be saved. ; SAVESIZE EQU SAVEEND-SAVIMAGE ; Define buffer image save-area size ; ; The next two symbols refer to locations within BIOS which ; CPM3BUFF uses to perform console I/O. ; They probably conflict with symbols within your BIOS ; source. If they do, and you incorporate this source ; into your BIOS source, you can delete them so that the ; references to those symbols will be correctly resolved. ; CONIN EQU BIOS+(3*3) ; CONIN position in BIOS vector table CONOUT EQU BIOS+(4*3) ; CONOUT position in BIOS vector table ; ; ; The rest of the symbols defined here are for internal use within ; CPM3BUFF. If the conflict with symbols defined in your BIOS source, ; change them AND any references to them before merging CPM3BUFF.ASM ; into your BIOS source. ; CTRLA EQU 'A'-40H ; Define.. CTRLB EQU 'B'-40H CTRLC EQU 'C'-40H CTRLD EQU 'D'-40H CTRLE EQU 'E'-40H CTRLF EQU 'F'-40H ; ..symbols.. CTRLG EQU 'G'-40H CTRLH EQU 'H'-40H CTRLI EQU 'I'-40H CTRLJ EQU 'J'-40H CTRLK EQU 'K'-40H ; ..for.. CTRLL EQU 'L'-40H CTRLM EQU 'M'-40H CTRLN EQU 'N'-40H CTRLO EQU 'O'-40H CTRLP EQU 'P'-40H ; ..all.. CTRLQ EQU 'Q'-40H CTRLR EQU 'R'-40H CTRLS EQU 'S'-40H CTRLT EQU 'T'-40H CTRLU EQU 'U'-40H ; ..control.. CTRLV EQU 'V'-40H CTRLW EQU 'W'-40H CTRLX EQU 'X'-40H CTRLY EQU 'Y'-40H CTRLZ EQU 'Z'-40H ; ..characters ; MAXCTRL EQU CTRLX ; editing character with highest value ; ; ; The next three symbols define the ASCII values for ; cursor positioning. Refer to your terminal documents ; for the correct values for your terminal ; ; ; ; Define Cursor Right code for console used CURSORRT EQU 'F'-'@' ; (CTRLF on ADDS Viewpoint, .. ;CURSORRT EQU 'L'-'@' ; CTRLL on LSI, etc.) ; CURSORLF EQU 'H'-'@' ; Define Cursor Left code for console used ; ; (CTRLH on ADDS, may differ on others) ; BELL EQU 'G'-'@' ; Define the Bell character for console used ; DELETE EQU 07FH ; Define Delete Key value ; ; ;STRTBUF: ; Initialization entry point. This routine must.. ;; ; ..be entered at the end of every warm boot. It.. ;; ; ..replaces the normal entry in the BDOS function.. ;; ; ..table with a pointer to the CPM3BUFF entry addr. ; RET ; This RET will be changed to a NOP by the cold-boot.. ;; ; ..routines IF the correct code is found in the BDOS ;; ; ..BDOS, to enable the CP/M+ (3.x) BDOS function 10. ;; ; Otherwise, the standard BDOS routine will be used. ;; ; LD DE,CPM3BUFF ; LD HL,BDOSTABL+(2*10) ; LD (HL),E ; INC HL ; LD (HL),D ; RET ;; ;; CPM3BUFF: ; Main entry point to CP/M 3.x style console buffer.. ; ; ..routine CALL LOADADDR+BIAS ; Get caller's buffer address INC HL ; Bump past the length byte PUSH HL ; Copy address.. POP DE ; ..into End-of-Message pointer ; READBUFF: ; Start of main loop PUSH DE ; Save End-of-Message pointer.. PUSH HL ; ..and Cursor Pointer CALL CONIN ; Go get data byte from user POP HL ; Restore Cursor Pointer and.. POP DE ; ..End-of-Message pointer CALL PROCESCH+BIAS ; Process the input character JR READBUFF ; Repeat until user types CR or LF, or.. ; ; ..a ^C as first byte in message ; PROCESCH: ; Process the character just read CP DELETE ; Is data byte DELETE? JR Z,DELPROC ; Process DELETE key like BACKSPACE CP MAXCTRL+1 ; Test for valid range, process as data.. JR NC,STORE ; ..if NOT an editing control character PUSH HL ; Save cursor pointer LD HL,PROCTABL+BIAS ; Load pointer to procedure vector table LD C,A ; Use data byte as a.. LD B,0 ; ..pointer into the.. ADD HL,BC ; ..procedure table LD C,(HL) ; Add in the.. ADD HL,BC ; ..procedure offset EX (SP),HL ; Restore HL value from stack RET ; Pop computed procedure address into PC ; ; PROCTABL: DB CTL@PROC-$ ; "null" character (00H) DB CTLAPROC-$ ; Vector.. DB CTLBPROC-$ DB CTLCPROC-$ DB CTLDPROC-$ DB CTLEPROC-$ DB CTLFPROC-$ ; ..table.. DB CTLGPROC-$ DB CTLHPROC-$ DB CTLIPROC-$ DB CTLJPROC-$ DB CTLKPROC-$ ; ..for.. DB CTLLPROC-$ DB CTLMPROC-$ DB CTLNPROC-$ DB CTLOPROC-$ DB CTLPPROC-$ ; ..Control-Character.. DB CTLQPROC-$ DB CTLRPROC-$ DB CTLSPROC-$ DB CTLTPROC-$ DB CTLUPROC-$ ; ..processing DB CTLVPROC-$ DB CTLWPROC-$ DB CTLXPROC-$ ; ; STORE: ; Non-functional Control-character.. ; ..or ordinary data byte CTL@PROC: CTLEPROC: CTLIPROC: CTLLPROC: CTLNPROC: CTLOPROC: CTLQPROC: CTLTPROC: CTLUPROC: CTLVPROC: PUSH AF ; Save data byte CALL CALCETOB+BIAS ; Get total message length in B-reg LD A,B ; ..and buffer size in C-reg CP C ; If buffer capacity exhausted.. JR NC,TOOMANY ; ..then go to warn user CALL CALCLTOE+BIAS ; Get byte count to right of cursor JR Z,NOPUSH ; If 0, then no data to push to right PUSH DE ; Copy End-of-Message.. POP IX ; ..address to IX-reg PUSHLOOP: ; Shift everything from cursor one byte to right DEC IX ; Decrement index reg LD A,(IX+0) ; Move indicated byte.. LD (IX+1),A ; ..right one byte DJNZ PUSHLOOP ; Loop on byte count NOPUSH: POP AF ; Restore data byte LD (HL),A ; Plug into message at cursor location CALL WRITEIT+BIAS ; Write the current data byte INC DE ; Bump End-of-Message pointer INC HL ; Bump cursor pointer WRITOEND: ; Re-write any bytes to right of cursor position CALL CALCLTOE+BIAS ; Get byte count to right of cursor PUSH AF ; Save data byte and Flags reg PUSH BC ; Save current byte count CALL WRITLTOE+BIAS ; Re-write any bytes which were moved POP BC ; Restore current byte count POP AF ; Restore data byte and Flags reg ; ; If cursor at right end of message, then.. RET Z ; ..exit to main loop.. ; ; Else recover cursor position on screen ; CTLBLLUP: ; Move cursor left on screen count (B-reg) bytes PUSH BC ; Save current byte count CALL CTLAPROC+BIAS ; Move cursor one byte to left on screen POP BC ; Restore current byte count DJNZ CTLBLLUP ; Decrement byte count and loop until done RET ; ; CTLGPROC: ; Eat character AT cursor position CALL CTLFPROC+BIAS ; Position cursor to right of target character DEC B ; If there wasn't any target character.. RET M ; ..(cursor at end of message), then exit.. ; ; ..else fall into BACKSPACE routine ; CTLHPROC: ; Eat character TO LEFT OF.. DELPROC: ; ..cursor position (Backspace AND delete keys) CALL CALCLTOB+BIAS ; Get byte count to left of cursor RET Z ; Exit if there are none CALL DRAGLEFT+BIAS ; Delete left character and drag rest to left JR WRITOEND ; Re-write any bytes to right of cursor.. ; ; ..and exit to main loop ; CTLCPROC: ; Control-C CALL CALCLTOB+BIAS ; If ^C is not first byte in buffer.. JR NZ,STORE ; ..then process as any other data byte CALL WRITEIT+BIAS ; If it is the first byte in buffer.. JP 000H ; ..then display it and do warm boot ; ; TOOMANY: ; Warn user the buffer is FULL!!!! POP AF ; Throw away the data byte and adjust Stack JR RINGBELL ; Go to ring the Bell and exit to main loop ; ; CTLBPROC: ; Reset cursor to START or END of message CALL CALCLTOB+BIAS ; Get byte count to left of cursor ; ; If any bytes to left of cursor, then.. JR NZ,CTLBLLUP ; ..reset cursor to START of message ; ; If none, then reset cursor to END of message ; CTLBRGHT: ; Re-position cursor to right end of message on screen CALL CALCLTOE+BIAS ; Get byte count to right of cursor RET Z ; If none, then exit CTLBRLUP: PUSH BC ; Save current byte count CALL CTLFPROC+BIAS ; Move cursor one byte to right on screen POP BC ; Restore current byte count DJNZ CTLBRLUP ; Decrement byte count and loop until done RET ; ; CTLRPROC: CTLWPROC: ; Restore previous message if buffer empty, else.. ; ; ..re-position cursor to right end of message CALL CALCETOB+BIAS ; Get total current message size ; ; If buffer is NOT empty, then.. JR NZ,CTLBRGHT ; ..reset cursor to END of message, else.. ; ; ..restore previous message image: ; ; Condition flags for MOVEPROC routine: ; ; ..(Not-Zero [NZ] and Carry [C]) XOR A ; ..Set accumulator = 0.. SUB D ; ..Subtract some non-zero reg to force.. ; ; ..a Carry with a non-zero result ; ; (D-reg will always be non-zero, since.. ; ; ..Save-Area will NEVER be in Page 0) CALL MOVEPROC+BIAS ; Call routine to move message image CALL LOADADDR+BIAS ; Get Buffer address INC HL ; Bump to first data byte ; WRITLTOE: ; Write data bytes from current cursor position.. ; ; ..to end-of-message CALL CALCLTOE+BIAS ; Get byte count to right of cursor JR Z,WRITPADS ; If none, write pad bytes at end and exit WRITLOOP: LD A,(HL) ; Get byte at cursor position CALL WRITEIT+BIAS ; Write it to screen INC HL ; Bump cursor pointer DJNZ WRITLOOP ; Loop until all bytes written WRITPADS: ; Write two pad blanks at end of message on screen LD A,' ' ; Load blank character CALL WRITEA+BIAS ; Write.. CALL WRITEA+BIAS ; ..two blanks CALL CRSRLEFT+BIAS ; Re-position cursor.. JR CRSRLEFT ; ..back over the two blanks, and exit ; ; CTLPPROC: ; process ^P (echo screen to printer) toggle: LD A,(CTLPTOGL) ; Load current ^P toggle from BDOS XOR 01H ; Invert it LD (CTLPTOGL),A ; Store it back into BDOS area RET Z ; If it was ON, return to main loop RINGBELL: LD A,BELL ; But if it was OFF, warn user.. JR WRITEA ; ..that it is ON now!! ; ; CTLAPROC: ; Move cursor one byte left on screen CTLSPROC: ; (Word-Star compatibility) CALL CALCLTOB+BIAS ; Get byte-count to LEFT of cursor RET Z ; If zero, then exit DEC HL ; Adjust Cursor Pointer CALL LEFTSPAC+BIAS ; Test if character under cursor.. ; ; ..is Control Character, adjust screen if so JR CRSRLEFT ; Go shift cursor left one byte and exit ; ; CTLFPROC: ; Move cursor right one byte on sceen CTLDPROC: ; (Word-Star compatibility) CALL CALCLTOE+BIAS ; Get byte count to right of cursor RET Z ; If zero, then exit LD A,(HL) ; If not zero.. INC HL ; ..then test for.. CP ' ' ; ..control-character.. CALL C,CRSRIGHT+BIAS ; ..and move cursor TWO bytes on screen CRSRIGHT: LD A,CURSORRT ; Load cursor-to-right control JR WRITEA ; Write to screen and exit ; ; CTLKPROC: ; Clear all bytes to RIGHT of cursor CALL CALCLTOE+BIAS ; Get byte-count to RIGHT of cursor RET Z ; If zero, then exit CTLKLOOP: PUSH BC ; Save current byte count CALL CTLGPROC+BIAS ; Delete the byte AT the cursor POP BC ; Restore current byte count DJNZ CTLKLOOP ; Decrement byte count and loop until done RET ; ; CTLJPROC: ; Line-Feed (treated as a Carriage-Return) LD A,CTRLM ; Force data-byte to Carriage-Return CTLMPROC: ; Carriage-Return (signals user is done) POP BC ; Throw away "Return to main loop".. ; ; ..(now a RET will return to BDOS!) CALL WRITEA+BIAS ; Write the Carriage-Return to screen CALL CALCETOB+BIAS ; Get total message length in B-reg ; ; MOVEPROC: ; Move message from buffer to save, or vice-versa: ; ; If entered with Zero-flag set, then set length byte to zero & exit. ; If entered with Carry-flag set (Zero-flag will NOT be set in this case) ; ..then move buffer save-area to user's buffer, and exit ; If entered with NEITHER Carry-flag NOR Zero-flag set, ; ..then move user's buffer to save-area, and exit ; CALL LOADADDR+BIAS ; Get message buffer address LD (HL),B ; Plug byte count into message length byte.. RET Z ; Dont bother saving buffer if it's empty LD DE,SAVEAREA ; Get buffer save-area address JR NC,GETCOUNT ; If direction flag set.. EX DE,HL ; ..then swap pointers to restore save-image GETCOUNT: LD C,SAVESIZE ; Set maximum move-length LD A,(HL) ; Get count from first byte of source buffer LD B,0 ; Zero hi-order byte of size-regs CP C ; If message is smaller than target buffer.. JR NC,OVRLIMIT ; ..then use actual message size from.. LD C,A ; ..count in first byte of source buffer OVRLIMIT: LD A,C ; Save number of bytes moved in A-reg INC BC ; Bump length to account for byte count LDIR ; Move byte count and message image LD (SAVEAREA),A ; Set save area byte count to.. ; ; ..actual number of bytes moved RET ; ; CTLXPROC: ; Clear all bytes to LEFT of cursor CALL CALCLTOB+BIAS ; Get byte-count to LEFT of cursor RET Z ; If zero, then exit CTLXLOOP: PUSH BC ; Save current byte count CALL CTLHPROC+BIAS ; Call routine to delete one byte to left POP BC ; Restore current byte count DJNZ CTLXLOOP ; Decrement byte count and loop until done RET ; ; DRAGLEFT: ; Shift bytes to right of cursor left in buffer DEC HL ; Decrement End-of-Message pointer DEC DE ; Decrement cursor pointer CALL LEFTSPAC+BIAS ; check if character moved onto.. ; ; ..is a control-character CALL CALCLTOE+BIAS ; Get byte-count to RIGHT of cursor JR Z,CRSRLEFT ; If zero, then no bytes to drag PUSH HL ; Copy cursor pointer.. POP IX ; ..to IX-reg DRAGLOOP: LD A,(IX+1) ; Get character to right of cursor.. LD (IX+0),A ; ..and shift it left one byte INC IX ; Bump pointer DJNZ DRAGLOOP ; Loop on byte-count ; CRSRLEFT: ; Shift cursor left on screen one byte LD A,CURSORLF ; Load Control Character to shift cursor left ; WRITEA: ; Write byte in A-reg to console device PUSH AF ; Save AF-regs WRITECHR: ; Enter here if AF-regs already PUSHed PUSH HL ; Save.. PUSH DE ; ..rest of.. PUSH BC ; ..registers LD C,A ; Set up for CONOUT call CALL CONOUT ; Call standard BIOS console output routine POP BC ; Restore.. POP DE ; .. POP HL ; .. POP AF ; ..registers RET ; ; LEFTSPAC: ; Adjust cursor on screen when back-spacing.. ; ; ..over control characters LD A,(HL) ; Get byte at cursor position CP ' ' ; Is it a control character RET NC ; No - return to caller JR CRSRLEFT ; Yes - adjust cursor one byte left on screen.. ; ; ..and return to caller ; WRITEIT: ; Write a data byte to screen. ; ; (control characters written with carat [e.g. ^Z ]) PUSH AF ; Save data byte CP ' ' ; Is it a control character? JR NC,WRITECHR ; No - just go and write it and exit ADD A,'@' ; Yes - force it to visible range of ASCII PUSH AF ; Save it LD A,'^' ; Go display.. CALL WRITEA+BIAS ; ..the carat ( ^ ) POP AF ; Restore the "visibleized" character JR WRITECHR ; Go to write it and exit ; ; LOADADDR: ; Load buffer address into (HL-reg).. ; ; ..and maximum message size into (C-reg) LD HL,(BUFFADDR) ; Load buffer address LD C,(HL) ; Load Maximum size INC HL ; Bump past max-size to byte-count RET ; ; CALCETOB: ; Compute current message length PUSH DE ; Save End-of-Message pointer PUSH HL ; Save cursor position pointer JR LODBEGAD ; Go to load buffer address ; ; CALCLTOE: ; Compute byte count from cursor to End-of-Message PUSH DE ; Save End-of-Message pointer PUSH HL ; Save cursor position pointer JR CALCSUB ; Go to swap pointers and.. ; ; ..compute their difference ; ; CALCLTOB: ; Compute byte count from start of buffer to cursor PUSH DE ; Save End-of-Message pointer PUSH HL ; Save cursor position pointer EX DE,HL ; Swap cursor pointer into minuend register LODBEGAD: CALL LOADADDR+BIAS ; Get buffer address into subtrahend reg INC HL ; Bump past byte-count bucket CALCSUB: EX DE,HL ; Swap pointers CP A ; Clear carry without harming A-reg SBC HL,DE ; Subtract subtrahend from minuend LD B,L ; Load result into B-reg POP HL ; Restore cursor position pointer POP DE ; Restore End-of-Message pointer RET ; ; CODESIZE EQU $-CPM3BUFF ; Define size of code to be moved.. ; ; ..during enablement of routine ; ; Needed only if CPM3BUFF is moved into place.. ; ; ..by a TPA program as a daemon, a la DDT ; ; NEXTPAGE EQU (($/100H)+1)*100H ; Define a symbolic reference to.. ; ; ..the next page boundary IFTRUE PATCH ; PATCH-AREA: The following 32 lines define 256 bytes of potential ; patch space, beginning at the defined buffer save-area. ; If the statement above defining CODESIZE is moved down ; below these lines, then these self-referencing words ; will be moved into the High-Memory area where the CPM3BUFF ; module resides, and can serve as patch-space for any ; patching requirement. The only caveat to using this ; area is that ANY USE OF THE SYMBOL "SAVESIZE" IN CPM3BUFF ; MUST BE PATCHED TO REFLECT THE REDUCED SIZE OF THE SAVE-AREA! ; ==== ; Another reason for including these self-referencing ; words in the CPM3BUFF save-area is that it allows the ; user to use a de-bugger to easily determine the highest ; byte over-written during use of the save-area, and ; therefore to determine the longest message images input ; thru BDOS function 10 calls. Frequent monitoring of this ; information after installation can be helpful in determining ; the optimum size for the save-area, and reductions can ; be made by re-assembling the module with a smaller value ; defined for SAVESIZE. ; DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 DW $+BIAS+0,$+BIAS+2,$+BIAS+4,$+BIAS+6 ENDIF ;===========================END OF BUFFER ROUTINE========================= ; END