; PROGRAM: ZMSAVE (derived from original MATESAVE) ; AUTHOR: Jay Sage ; CREATED: February 26, 1986 ; REVISED: May 23, 1990 ; VERSION: 1.1 ; Version 1.1, Jay Sage, May 23, 1990 ; ; Added code to handle PMATE's soft carriage return and soft hyphen ; characters (see routine PUTSTR). Also added a type 3 header so that ; at some point the program might be able to run at 200H and figure ; out for itself the address of PMATE's text buffer by examining the ; address at 01c9h. It is better to patch in the proper address, since ; then the program can run even after low memory has been modified. version: macro db '1.1' endm date: macro db '05/23/90' endm ; This program saves text in PMATE's editing buffers after a system crash or ; after an accidental exit from the program. The program must be assembled or ; patched with the address of the start of PMATE's text buffer. Each of ; PMATE's buffers is examined separately and written out to its own file with ; the name BUFFERn.TXT, where n is either 'T' or a number from 0 to 9. Unless ; the option 'S' is given, any existing files with the name BUFFER-?.TXT are ; deleted before new ones are created. ; ; SYNTAX: MATESAVE // display help screen ; MATESAVE save text from memory ; MATESAVE S save old BUFFER-?.TXT files ; ; The patch point for the address of the beginning of the PMATE buffer is near ; the beginning of the file, and there is a text string to make it easy to ; identify the patch point. For any given version of PMATE, this address can ; be obtained by examining the word at memory location 01C9h. Since this is ; so near the beginning of memory, there is no way for this program to get the ; value automatically from memory. ;============================================================================= ; E X T E R N A L D E C L A R A T I O N S ext print,pstr ext codend,mhl5dc ext fxo$open,fxo$close,fx$put,f$delete ;============================================================================= ; E Q U A T E S S E C T I O N textaddr equ 001c9h ; Address with address of PMATE ; ..text buffer start textbuffer equ 0692fh ; Address of beginning of PMATE ; ..text buffer dfcb equ 005ch ; Default file control block cr equ 00dh lf equ 00ah tab equ 009h null equ 000h bell equ 007h ;============================================================================= ; M A I N C O D E S E C T I O N .z80 ; Use Zilog opcodes jp start ; Jump to actual start of code db 'Z3ENV' ; Standard Z header db 1 ; Type 1 program env: dw 0 ; Z3ENV address will be here dw 0 ; Load address here for type-3 db 'PMATE TEXT BUFFER ADDRESS=' tbufpointer: dw textbuffer start: ld hl,0 ; Save stack pointer add hl,sp ld (oldstack),hl ld sp,oldstack ; Set up local stack call initialize ; Perform initialization tasks call signon ; Display signon message ld a,(dfcb+1) ; Check command-line options cp ' ' ; If none, run program jr z,start1 cp '/' ; Help option jp z,help cp 'S' ; Save-old-files option jr z,start2 ; If so, skip over clearfiles jp badoption ; Bad option if we reach here start1: call clearfiles ; Clear out old saved text files start2: call savetext ; Save the text in PMATE's buffers exit: ld sp,(oldstack) ; Restore original stack pointer ret ;============================================================================= ; P R O G R A M S U B M O D U L E S ;----------------------------------------------------------------------------- ; SAVETEXT - save the text in PMATE's buffers savetext: ; Just in case, put in dummy end-of-buffer markers ld hl,(6) ; Get address of start of BDOS ld l,0 ; Point to beginning of page ld c,10 ; Set count of 10 ld a,l ; Get 0 into A also fill: dec hl ld (hl),a dec c jr nz,fill ; Save text in each buffers in sequence ld hl,(tbufpointer) ; Read starting address of PMATE text ld de,xfcb ; Set pointer to extended FCB ld bc,nametable-1 ; Point to table of buffer names dec hl ; Adjust for pre-increments below nextbuf: inc bc ; Point to next buffer name inc hl ; Point to beginning of next buffer ld a,(bc) ; Get name of next buffer ld (fname+7),a ; Put it in as file name suffix ld (bufnam1),a ; ..and in two places in ld (bufnam2),a ; ..the message to user or a ; See if end of buffers ret z ; ..and return if so ld a,(hl) ; Get first byte of buffer or a ; ..and test to see if anything there jr z,nextbuf ; If empty, go on to next buffer call openfile ; Open a file for this buffer push bc ; Save pointer to buffer name call putstr ; Save this buffer in the file call closefile ; Close the file call usermsg ; Display message to user pop bc ; Restore pointer to buffer name jr nextbuf ; On to next buffer nametable: db 'T0123456789' db 0 ; End marker ;----------------------------------------------------------------------------- ; HELP - display help screen if requested with command-line option help: call print db 'This program saves text left in ' db 'memory by PMATE after an accidental' db cr,lf db 'exit from the program. Each of PMATE''s ' db 'buffers is checked, and if text' db cr,lf db 'is found, it is stored in a file with ' db 'the name BUFFER-n.TXT, where n is' db cr,lf db 'the name of the buffer (T or 0..9). ' db 'A message is displayed showing' db cr,lf db 'which buffers had text and how many ' db 'characters were saved.' db cr,lf,lf db 'The program must be patched near the ' db 'beginning of the file with the' db cr,lf db 'address at which PMATE''s text buffer begins.' db cr,lf,lf db 0 syntax: call print db ' SYNTAX:',tab,'MATESAVE',tab,tab db 'delete old files and save text' db cr,lf db tab,tab,'MATESAVE S',tab,tab,'save old BUFFER-?.TXT files' db cr,lf db tab,tab,'MATESAVE /',tab,tab,'display this help message' db cr,lf,lf db 0 jp exit ; Terminate the program ;----------------------------------------------------------------------------- ; BADOPTION - display 'bad option' message and then help screen badoption: ld (badopt),a ; Store option char in message call errormsg ; Display error message header call print db 'bad command line option "' badopt: db ' ' db '"' db cr,lf,lf,0 jp syntax ; Continue with syntax help screen ;----------------------------------------------------------------------------- ; CLEARFILES - erase any existing files with the names BUFFER-?.TXT clearfiles: ld de,fcb ; Point to fcb in extended fcb call f$delete ; Delete the old files ret ;============================================================================= ; S U B R O U T I N E S S E C T I O N ;----------------------------------------------------------------------------- ; SIGNON - display program signon message signon: call print db cr,lf db 'MATESAVE Version ' version ; Macro to fill in version db ' (' date ; Macro to fill in date of version db ')' db cr,lf,lf,0 ret ;----------------------------------------------------------------------------- ; INITIALIZE - perform initialization tasks initialize: call codend ; Set up file buffer address ld (bufaddr),hl ; ..at end of code ld a,'?' ; Define ambiguous file spec ld (fname+7),a ; ..in extended fcb ld a,0 ; Select default drive in fcb ld (fcb),a ret ;----------------------------------------------------------------------------- ; ERRORMSG - display error message prefix errormsg: call print db bell db '*** ERROR ==> ' db 0 ret ;----------------------------------------------------------------------------- ; OPENFILE - open output file using buffered file I/O openfile: ld de,xfcb ; Point to extended FCB call fxo$open ; Try to open the file for output ret nz ; Return if successful ; ..else fall through to error msg nodir: call errormsg ; Print error message prefix call print ; Print error message text db 'no directory space' db cr,lf,0 jp exit ; Terminate program ;----------------------------------------------------------------------------- ; CLOSEFILE - close the output file closefile: ld de,xfcb ; Point to extended FCB call fxo$close ret nz ; Return if successful ; ..else fall through to error msg diskfull: call errormsg ; Display error message prefix call print db 'disk full' db cr,lf,0 jp exit ; Terminate program ;----------------------------------------------------------------------------- ; USERMSG - display message to user about buffer being recovered usermsg: push hl ; Save pointer to PMATE text ld h,b ; Move character count from ld l,c ; ..BC to HL ld de,buffermsg ; Convert to decimal text in call mhl5dc ; ..the message string ld hl,buffermsg ; Now display the message call pstr pop hl ; Restore pointer to PMATE text ret buffermsg: db '????? bytes saved from buffer ' bufnam1: db '?' ; Place for name of buffer db ' to file BUFFER-' bufnam2: db '?' db '.TXT' db cr,lf db 0 ;----------------------------------------------------------------------------- ; PUTSTR - put null-terminated string into output file and return the character ; count in BC ; ; 05/23/90: The code was improved to handle the special soft return and hyphen ; characters. In memory PMATE uses several special characters. When it writes ; the file to disk, it puts in different characters. They are as follows: ; ; purpose in memory in file ; -------------------------------- --------- ---------- ; soft carriage return E0 8D 0A ; soft return with auto indent E1 8D 0A ; soft hyphen E2 AD 0D 0A ; soft hyphen with auto indent E3 AD 0D 0A ; ; So that the recovered text can be edited by PMATE, the code below detects ; the special characters and writes the proper data to the file. putstr: ld bc,0 ; Preset character count to zero putstr0: ld a,(hl) ; Get character or a ; See if end of buffer ret z ; If so, quit now cp 0e0h ; See if soft carriage return jr z,softcr cp 0e1h jr nz,notcr softcr: ld a,cr+80h ; Write cr with high bit set call putchar jr putlf notcr: cp 0e2h ; See if soft hyphen jr z,softhy cp 0e3h jr nz,nothy softhy: ld a,'-'+80h ; Write hyphen with high bit set call putchar ld a,cr ; Then write cr call putchar jr putlf nothy: call putchar ; Write out the character cp cr ; See if carriage return jr nz,putdone ; If not, we are done writing putlf: ld a,lf ; Write out a linefeed call putchar putdone: inc hl ; Point to next character jr putstr0 ; ..and process it putchar: call fx$put ; Save character in file jp z,diskfull inc bc ; Increment character count ret ;============================================================================= ; I N I T I A L I Z E D D A T A A R E A xfcb: ; Extended file control block db 8 * 8 ; 8K buffer db '?' ; EOF flag dw 0 ; Byte counter dw 0 ; Next byte pointer bufaddr: dw 0 ; File buffer address fcb: db 0 ; Drive fname: db 'BUFFER-?' ; File name db 'TXT' ; File type ds 24 ; Rest of FCB ;============================================================================= ; U N I N I T I A L I Z E D D A T A A R E A ds 30 * 2 ; Space for local stack oldstack: ds 2 ; Space for old stack pointer end