TITLE FXDRVR: A Special WordStar Font Driver ; ; ; FXDRVR: A Special Font Driver for WordStar and the Epson FX-80 ; ; Copyright (c) 1982, 1983, 1984 by Paul J. Gans. This version of ; FXDRVR.MAC is hereby placed into public domain. Permission ; is granted to SIG/M to distribute this file freely for non- ; commercial personal use only. ; ; ; Revision Record: ; ; Version 1.0 January 15, 1982 Original version. ; 2.0 January 19, 1982 Auto program load added. ; 2.1 September 17, 1982 Emphasized graphics added. ; 2.2 January 19, 1983 Updated to work with Epson ; Graphtrax Plus ROMs. ; 3.0 December 19, 1984 Name changed to FXDRVR, Down- ; load font used instead of ; graphics. ; ; The current version is 3.0.0 of 12/19/1984. ; PAGE 58 ; ; This is a special font driver for WordStar. It allows the user to ; print special characters in a WordStar document on an Epson FX-80. ; This is done by making use of the FX-80's ability to accept a user- ; defined character set. Included with this font driver is a set of ; greek upper and lower case characters and some special mathematical ; symbols. ; ; Before this program can be used with WordStar, WordStar must be prop ; erly set up to match the assumptions made by this program. Configur ; ation instructions for WordStar are given in the file FXDRVR.DOC. ; ; This program is designed to be assembled with Microsoft's M80 assem ; bler and follows the conventions of that program. This assembler was ; chosen because most of the code below is designed to be executed at an ; address other than that into which it will be loaded by CP/M. A ; suitable command sequence to assemble and link this program is: ; ; >M80 =FXDRVR/L <== the /L produces a .PRN file, ; omit it if not desired. ; ; >L80 FXDRVR,FXDRVR/N/E ; ; After FXDRVR has been assembled and converted to a .COM file, the ; character set to be downloaded must be appended to it. The file con ; taining this character set must meet the assumptions of the program. ; The character set must contain 12 byte character definitions as ; specified in the Epson FX-80 manual. They may start at an arbitrary ; character position (as defined by the FFCHAR equate below) and may end ; at an arbitrary character position (as defined by the LFCHAR equate ; below). All characters between the first and last character inclusive ; MUST be present in the font. Any or all of the characters may be ; blank; many of the characters are blank in the set included here. ; ; The character set file is appended to the font driver at its very end. ; To make it easier to find the end of FXDRVR, a line of 16 asterisks ; has been placed at the end of the program. The first 16 bytes of the ; download font should overlay the asterisks. ; ; ; The action of the driver is simple. A set of control codes, presently ; the numbers 81H through 86H, cause the driver to instruct the Epson ; FX-80 to enter one or another of its printing modes. Control codes ; are: ; ; 81H downloaded font mode ; 82H italic mode ; 83H emphasized mode ; 84H condensed mode ; 85H elite mode ; 86H double strike mode ; ; These control codes are sent by WordStar when the appropriate special ; characters are typed into a document by the user. Just how these ; special characters are mapped into control codes is set by user cust- ; omization of the printer area of WordStar. A possible mapping is: ; ; ^A Enter elite mode ; ^N Leave elite mode ; ^W Toggle italic mode ; ^E Toggle emphasized mode ; ^R Toggle condensed mode ; ^Y Toggle MX-80 double strike mode ; ^Q Used downloaded font for next character ; ; It is suggested that condensed mode (the ^R toggle) not be used in new ; documents as future versions of this program may use the ^R toggle for ; other purposes. ; ; When the alternate font signal (^Q) is recognized in the output from ; WordStar, FXDRVR outputs the control codes sequence 0x1b 0x25 0x01 ; 0x00. This puts the FX-80 into alternate character set mode (the ; downloaded set). FXDRVR then accepts exactly one more character from ; WordStar, transmits it to the FX-80, and then transmits the code ; sequence 0x1b, 0x25, 0x00, 0x00 to the FX-80. This last code sequence ; returns the FX-80 to the normal character set. ; ; The other mode codes function as toggles. Initially all modes are ; off. When a mode code is recognized in the input character stream, ; the corresponding mode is toggled. That is, if it was off, it is now ; turned on and vice versa. When a mode is changed, the corresponding ; string of bytes to perform that action is sent to the printer by the ; driver program. ; ; The driver appears to the user as a normal .COM file. It is invoked ; as: ; ; FXDRVR wsname [filename.ext] ; ; where wsname is the name of the WordStar file. and filename.ext is an ; optional file name. The special driver relocates itself in upper ; memory and patches itself into the normal BIOS call table. It will ; then look for and load WordStar under the name WS.COM, first searching ; the default disk and then, if not found, the A drive. Execution will ; then be turned over to WordStar, which will then work in a normal ; fashion, loading filename.ext as a D mode file for editing if it is ; specified. ; ; When WordStar finishes, it will return control to the driver which ; will reset all pointers and memory locations that it changed, thus ; restoring those locations to their original state. FXRVR ends with a ; return statement. ; ; ; Technical notes: ; ; There is nothing special about the font downloaded to the printer. ; The font can be edited, or other fonts created, with nothing more than ; the information provided by Epson in the FX-80 User's manual. ; ; This program has gone through a number of versions. Versions 1 and 2 ; were written for the Epson MX-80 with Graphtrax. Changes were needed ; from time to time as the codes used to control various printer func ; tions have sometimes changed as Epson has changed the Graptrax ROMs. ; ; The current version has been greatly restructured to take advantage of ; the downloadable character set feature of the Epson FX-80. Previous ; versions used the graphics capability of the MX-80; this version uses ; a true character set. ; ;----------------------------------------------------------------------------- ; .Z80 ; ; The definitions below should be changed to accomodate differing font ; sizes. FFCHAR is the decimal or hex equivalent of the first character ; to be downloaded, LFCHAR is the decimal or hex equivalent of the last ; character to be downloaded. ; FFCHAR EQU 000H ;First font character LFCHAR EQU 0FFH ;Last font character ; FSIZE EQU 12*(LFCHAR + 1 - FFCHAR) ;Font size DCOUNT EQU FSIZE + 5 ;Font size plus Epson codes ; FALSE EQU 0 TRUE EQU NOT FALSE ; LF EQU 0AH ;Line feed CR EQU 0DH ;Carriage return ESCAPE EQU 1BH ;Escape SPACE EQU 20H ;Space ; INCHR EQU 01H ;CP/M character input OUTCHR EQU 02H ;CP/M character output PCHAR EQU 05H ;CP/M character print DSTRNG EQU 09H ;CP/M display string at console CHRW EQU 0BH ;CP/M character waiting OPEN EQU 0FH ;CP/M open file READ EQU 14H ;CP/M sequential read SETDMA EQU 1AH ;CP/M set DMA function ; LENTRY EQU 05H ;BIOS list function entry number ; WBOOT EQU 0000H ;Normal warm boot entry point OPSYS EQU 0005H ;CP/M call location TPATOP EQU 0006H ;Where TPA top address is stored FCB EQU 005CH ;Default file control block FCB2 EQU 006CH ;Secondary file control block BUFFER EQU 0080H ;Input command line buffer TBASE EQU 0100H ;Normal program load address ; CCBASE EQU 80H ;Control codes lie exclusively CCLAST EQU 87H ; between CCBASE and CCLAST ; LENGTH EQU FIN-HMC+1 ;Length of code to relocate ; ; ASEG ORG 100H ; ; First we display a logo. ; START: LD SP,STACK ;Plan ahead, use a stack! LD DE,SIGNON ;Now for a short message LD C,DSTRNG ; from our sponsor... CALL OPSYS JR DOWNL ; SIGNON: DB 'The Special Graphics Driver ' DB CR,LF DB 'Version 3.0 (c) 1982, 1983, 1984 by ' DB 'Paul J. Gans' DB CR,LF DB 'All Commercial Rights Reserved.' DB CR,LF,'$' ; ; The next thing to do is to download the user-definable character set. ; FXDRVR expects this set to be appended to the end of this program, ; starting at location FONT. There should be exactly 3077 bytes at that ; location, the first five of which are 0x1b, 0x26, 0x00, 0x00, 0xff, ; which tell the FX-80 that 3072 bytes, 256 character code at 12 bytes ; per character, are to be downloaded. ; DOWNL: LD BC,DCOUNT ;Set up a counter LD HL,FONT ;Source of bytes ; DOWN1: PUSH BC ;Save counters and address PUSH HL LD E,(HL) ;Get a byte LD C,PCHAR CALL OPSYS ;Send it to the printer POP HL ;Regain address POP BC ;And counter INC HL ;Next address DEC BC LD A,B ;Check for zero OR C JR NZ,DOWN1 ;Do it again ; ; The actual driver code itself must be relocated to just below the ; BDOS, the LIST entry in the BIOS jump table changed to point to ; FXDRVR, and the jump address in location 5 (TPATOP) must be lowered to ; protect the driver. ; START2: LD HL,(TPATOP) ;Last available memory + 1 LD (FXDRVR+1),HL ;For CP/M jumps LD BC,LENGTH ;Length to be relocated XOR A ;Clear carry SBC HL,BC ;Where to put first byte ; PUSH HL ;Save first byte address PUSH HL ; twice for good luck LD BC,FXDRVR-HMC ;Offset to protected area ADD HL,BC ;First protected address EX (SP),HL ;Swap first and one protected address ; LD BC,HMC SBC HL,BC ;Compute offset LD (OFFSET),HL ;And save for later ; ; Fix the fixed addresses in FXDRVR. ; EX DE,HL ;Offset LD HL,RTABLE AGAIN: LD C,(HL) ;BC is actual value INC HL LD B,(HL) LD A,C ;If it is zero, we are done OR B JR Z,FIXUP LD A,(BC) ;Low byte of address ADD A,E ;Low byte of offset LD (BC),A ;Put it back INC BC ;Next LD A,(BC) ;High byte of address ADC A,D ;High byte of offset LD (BC),A ;Put it back INC HL JR AGAIN ; FIXUP: LD HL,(WBOOT+1) ;Get address of start of CCP LD BC,3*LENTRY-2 ;Jump table offset to address ADD HL,BC ;Actual jump table entry address LD C,(HL) ;Low byte of list address INC HL LD B,(HL) ;High byte of list address LD (PR1+1),BC ;Save for later DEC HL POP BC ;Relocated first protected address LD A,C ; plus 3 to accomodate ADD A,3 ; the relocated CP/M LD (HL),A INC HL LD A,B ADC A,0 LD (HL),A ;Patch jump table entry LD (TPATOP),BC ;Reset top of available memory ; LD HL,(WBOOT+1) ;Get and save warm-boot address INC HL ;Skip op code LD C,(HL) ;Load low byte INC HL LD B,(HL) ;Load high byte LD (WBOOTS),BC ;Save it ; LD DE,(OFFSET) ;Get the offset LD BC,ATLAST ;Unrelocated where to go at the end LD A,C ;Add offset to the unrelocated ADD A,E ; address of ATLAST LD C,A ; because when we want to use it, LD A,B ; its gonna be up there and not ADC A,D ; down here! LD B,A LD (HL),B ;Store the relocated ATLAST address DEC HL ; in the BIOS jump table LD (HL),C ; MOVIT: LD BC,LENGTH ;Number of bytes to move POP DE ;Where to put the bytes LD HL,HMC ;Where to get first byte LDIR ;Move it ; HMC0: JP HMC ;Go save page 0 stuff and load program ; OFFSET: DW 0 ;Temporary for offset ; ; Relocation table. ; RTABLE: DW NOPROG+1 DW NOPR1+1 DW HMC0+1 DW HMC+1 DW ATLAST+1 DW T00+1 DW T01+1 DW T02+1 DW T03+1 DW T04+1 DW T05+1 DW T06+1 DW T07+1 DW T08+1 DW T09+1 DW T10+1 DW T11+1 DW T12+1 DW T13+1 DW T14+1 DW T15+1 DW T16+1 DW T17+1 DW T18+1 DW T19+1 DW T20+1 DW T21+1 DW T22+1 DW T23+1 DW T24+1 DW T25+1 DW T26+1 DW T27+1 DW T28+1 DW T29+1 DW T30+1 DW T31+1 DW T32+1 DW T33+1 DW T34+1 DW T35+1 DW T36+1 DW T37+1 DW T38+1 DW T39+1 DW T40+1 DW T41+1 DW T42+1 DW T43+1 DW T44+2 DW T45+2 DW T46+1 DW T47+1 DW 0 ; ; ; HIGH MEMORY CODE ; ; The code below is moved to high memory and executed there. The first ; part of it is not part of the driver proper, but contains code to save ; page 0, load the program, and reset page 0. The second part is the ; driver proper. ; ; Save the secondary FCB. ; HMC: LD SP,HMC ;'Tis a fine thing we do! LD BC,16 ;Length of FCB as set up T00: LD DE,FILE2 ;Destination address LD HL,FCB2 LDIR ;Move it ; ; Set the file extension in the primary file control block to .COM, no ; matter what the user wants. ; LD HL,FCB+9 ;Point to the extension subfield LD A,'C' ;Do it LD (HL),A INC HL LD A,'O' LD (HL),A INC HL LD A,'M' LD (HL),A ;Done ; ; Save the input file buffer only if there is a second file name. ; LD HL,BUFFER LD A,(HL) ;Buffer length count CP 0 JR Z,NOPROG ;Nothing, not even a program name ; LD B,A ;Something is there. First skip INC HL ; any leading spaces SRCH1: LD A,(HL) ; by looking for a non-space INC HL CP SPACE JR NZ,SRCH2 ;Found a non-space DJNZ SRCH1 ;Keep it up till out of buffer ; ; No program name exists at all. Complain to the user. ; NOPROG: LD DE,MSG1 LD C,DSTRNG CALL OPSYS NOPR1: CALL REPR ;Reset printer JP WBOOT ; MSG1: DB 'No program name given.',CR,LF,'$' ; SRCH2: LD A,(HL) ;We are scanning the first file name CP SPACE ;Keep looking for the first space char JR Z,SRCH3 ;Found a space INC HL DJNZ SRCH2 ;Repeat till out of buffer T01: LD HL,BUFFR2 ;Show that there is nothing saved in LD (HL),B ; the command line buffer JR LOADPR ;Then go load the program without args ; SRCH3: INC B LD C,B ;Count of command line bytes to save LD B,0 T02: LD DE,BUFFR2 ;Where to save command line EX DE,HL LD (HL),C ;Save byte count first INC HL EX DE,HL LDIR ;Then the rest of the string JR LOADPR ;Then go load the program ; ; There is a program name present. First check to see if the file ; exists on the logged in disk. If not, check the A disk. If found, ; load the program at TBASE. If not found, complain bitterly. ; LOADPR: LD DE,FCB ;First, open the file LD C,OPEN CALL OPSYS ;Returns FF on failure INC A ;Was it FF? JR NZ,LOAD1 ;Jump if file found ; LD HL,FCB LD A,01H ;Disk A flag LD (HL),A EX DE,HL ;Try again. We even may have already LD C,OPEN ; tried this disk, but no matter CALL OPSYS INC A JR NZ,LOAD1 ;Got it this time ; ; The primary program file does not exist. Complain. ; T03: LD DE,MSG2 LD C,DSTRNG CALL OPSYS JP WBOOT ; MSG2: DB 'File not found.',CR,LF,'$' ; ; Load the primary file. Though the code below is not protected, no ; normal WordStar load ought to get this high in memory. If it does, ; bombs away! ; LOAD1: LD DE,TBASE ;Initial load address PUSH DE ;Save it LD C,SETDMA CALL OPSYS ; LOAD2: LD DE,FCB ;This is the primary loading loop. LD C,READ ; A sector is read into sequential CALL OPSYS ; memory until an endfile condition POP DE ; is found. OR A ;This checks for the endfile JR NZ,SETUP ;Non-zero is endfile LD HL,128 ;Update the DMA address ADD HL,DE PUSH HL ;And save it again EX DE,HL LD C,SETDMA CALL OPSYS JR LOAD2 ;Repeat till done ; ; It now remains to reset the FCB and BUFFER. ; SETUP: LD BC,16H ;Reset FCB from what was saved. LD DE,FCB T04: LD HL,FILE2 LDIR LD HL,FCB2 ;Reset FCB2 to empty LD (HL),B ; by storing a leading zero LD B,11 ; and 11 spaces LD A,SPACE SETUP1: INC HL LD (HL),A DJNZ SETUP1 T05: LD HL,BUFFR2 ;Reset the command line buffer if it LD A,(HL) ; isn't empty CP 0 ;Is it empty JP Z,TBASE ;Yes, go RUN INC A ;So we move the count as well LD C,A ;Set count LD B,0 LD DE,BUFFER LDIR JP TBASE ;That's it! ; ; Storage for FILE2 and BUFFR2. ; FILE2: DS 16 ;Secondary file control block BUFFR2: DS 80H ; ; ; THE WordStar DRIVER ; ; The driver proper is below. The first location is a jump to the true ; start of CP/M. A call to location 5 (the normal CP/M entry) results ; in a jump to the first protected address in high memory. That has now ; been changed so as to protect the driver. Hence the jump below, fil- ; led in by the relocator. ; FXDRVR: JP 0000H ;Jump to CP/M ; LD HL,0 ;Save the stack pointer ADD HL,SP ;Got it! T06: LD SP,STAK ;Set it to a local area PUSH HL ; and save old SP on it T07: LD HL,RCVR ;Now we put the stack recovery routine PUSH HL ; onto the stack so we can RET to it ; T08: LD HL,MODES ;Array of mode flags LD A,(HL) ;Graphics mode flag CP 0 ;Are we in graphics mode? T09: JP NZ,DOMAP ;Jump if we are ; LD A,C ;Character to A CP CCBASE ;Is it a mode toggle character? T10: JP C,PRINT ;If not, print it directly CP CCLAST ;Is it a weird character? RET NC ;If so, ignore it ; CP 81H ;Graphics character? JR Z,GRAF ;Jump if so ; INC HL ;Giant case statement: CP 82H ; HL points to proper mode T11: JP Z,ITAL ; flag INC HL CP 83H T12: JP Z,EMPH INC HL CP 84H T13: JP Z,COND INC HL CP 85H T14: JP Z,ELIT INC HL CP 86H T15: JP Z,DBLE ; ; We cannot get to this point in normal usage. Thus: ; LD DE,MSG3 LD C,DSTRNG CALL OPSYS HALT ;With prayers ; MSG3: DB 'HARD ERROR: Failure in case statement.' DB CR,LF DB 'System must be REBOOTED to continue' DB CR,LF,'$' ; ; The response to the various mode flags is coded below: ; GRAF: LD (HL),A ;Set graphics mode RET ; ITAL: LD A,(HL) ;Get ITALICS mode flag OR A ;(A): 00=off, FF=on CPL ;Does not change Z flag LD (HL),A ;Resave mode flag LD B,2 ;Send two bytes to EPSON T16: LD HL,ONITAL T17: JP Z,PRINTS ;Turn ITALICS on T18: LD HL,OFITAL T19: JP PRINTS ;Turn ITALICS off ; ONITAL: DB 1BH, 34H ;ON ITALICS string OFITAL: DB 1BH, 35H ;OFF ITALICS string ; EMPH: LD A,(HL) ;Get EMPHASIZED mode flag OR A ;(A): 00=off, FF=on CPL ;Does not change Z flag LD (HL),A ;Resave mode flag LD B,2 ;Send two bytes to EPSON T20: LD HL,ONEMPH T21: JP Z,PRINTS ;Turn EMPHASIZED on T22: LD HL,OFEMPH T23: JP PRINTS ;Turn EMPHASIZED off ; ONEMPH: DB 1BH, 45H ;ON EMPHASIZED string OFEMPH: DB 1BH, 46H ;OFF EMPHASIZED string ; COND: LD A,(HL) ;Get CONDENSED mode flag OR A ;Set flag register as above CPL ;Does not change Z flag LD (HL),A ;Resave mode flag LD B,1 ;Send one byte to EPSON T24: LD HL,ONCOND T25: JP Z,PRINTS ;Turn CONDENSED on T26: LD HL,OFCOND T27: JP PRINTS ;Turn CONDENSED off ; ONCOND: DB 0FH ;ON CONDENSED string OFCOND: DB 12H ;OFF CONDENSED string ; ELIT: LD A,(HL) ;Get EXPANDED mode flag OR A CPL LD (HL),A LD B,2 ;Send two bytes to EPSON T28: LD HL,ONELIT T29: JP Z,PRINTS T30: LD HL,OFELIT T31: JP PRINTS ; ONELIT: DB 1BH, 4DH ;ON ELITE string OFELIT: DB 1BH, 50H ;OFF ELITE string ; DBLE: LD A,(HL) ;Get DOUBLE STRIKE mode flag OR A CPL LD (HL),A LD B,2 ;Send two bytes to EPSON T32: LD HL,ONDBLE T33: JP Z,PRINTS T34: LD HL,OFDBLE T35: JP PRINTS ; ONDBLE: DB 1BH, 47H ;ON DOUBLE STRIKE string OFDBLE: DB 1BH, 48H ;OFF DOUBLE STRIKE string ; ; PRINT simply saves all registers and calls the CP/M BIOS print rou- ; tine. The proper address is stuffed into the call statement by the ; setup code. ; PRINT: PUSH AF ;Avoid trouble, save it all PUSH BC PUSH DE PUSH HL PR1: CALL 0 ;To be filled with the address POP HL ; of the CP/M print routine POP DE POP BC POP AF RET ; ; PRINTS will output the string of bytes whose start is pointed to by HL ; until B bytes are sent. ; PRINTS: LD C,(HL) ;Get a byte T36: CALL PRINT ;Print the character INC HL ;Point to next byte DJNZ PRINTS ;Keep on if more RET ;Else quit ; ; PRINTE will output the same bytes as PRINTS but in emphasized mode. ; PRINTE: LD DE,0 ;Clear DE PRE: LD D,(HL) ;Get new byte LD A,D ;Move it to A OR E ;Or in previous byte LD C,A ;Prepare to send it T37: CALL PRINT ;Then send it INC HL ;Point to next byte LD E,D ;Save old byte DJNZ PRE ;And repeat 12 times RET ;Then quit ; ; DOMAP (called that for historical reasons) puts the Epson into alter ; nate character set mode, outputs the character, and returns it to the ; ordinary (ROM) character set mode. ; DOMAP: XOR A ;Clear register T38: LD (MODES),A ;And reset graphics mode PUSH BC ;Save character to be printed LD B,4 ;Send 4 characters T39: LD HL,ONGR ;Start of sequence T40: CALL PRINTS ;Send sequence POP BC ;Regain character T41: CALL PRINT ;Print it LD B,4 ;Send 4 characters T42: LD HL,OFFGR ;Start of sequence T43: CALL PRINTS ;Print it RET ; ONGR: DB 1BH,25H,01H,00H ;Select alternate character set OFFGR: DB 1BH,25H,00H,00H ;Select normal character set ; RCVR: POP HL ;Before quitting, reset the stack LD SP,HL ; to what it was when WordStar RET ; set the return address ; ; At termination of WordStar various locations in the BIOS jump vector ; and in low memory have to be reset to their initial values. Note that ; initially, before the driver runs, locations 1 and 2 contain a jump to ; the BIOS jump table warm boot entry. When the driver runs, the ad- ; dress in the table is stored in WBOOTS below and the address of the ; routine below substituted for it. When WordStar warm boots, the rou- ; tine below will be entered. The routine will reset the BIOS table ; address to its original value, reset the LIST entry to its initial ; value, and return locations 5 and 6 in low memory to their initial ; values. ; ATLAST: LD HL,(FXDRVR+1) ;Original memory top LD (TPATOP),HL ; now restored T44: LD BC,(WBOOTS) ;Saved BIOS warm boot entry LD HL,(WBOOT+1) ;Address for BIOS entry INC HL ;Point to address part of jump LD (HL),C INC HL LD (HL),B ;BIOS warm boot entry restored ; DEC HL ;Address for BIOS entry DEC HL LD BC,3*LENTRY-2 ;Jump table offset to address ADD HL,BC ;Actual jump table entry address T45: LD BC,(PR1+1) ;Saved BIOS list entry LD (HL),C INC HL LD (HL),B ;BIOS list entry restored ; ; One last thing remains. The FX-80 should be reset to its power-up ; configuration. To that end a reset string is now sent to the printer. ; REPR: LD B,2 ;Two character string T46: LD HL,RESET ;Point to the string T47: CALL PRINTS ;Send it ; JP WBOOT ;THAT'S IT, FOLKS! ; RESET: DB 1BH, 64H ;FX-80 master reset string ; WBOOTS: DW 0 ;For original warm boot address DS 01EH ;For a local stack STAK: ; ; The MODE bytes are stored here. ; MODES: DB 0 ;Graphics mode flag DB 0 ;Italics mode flag MODEE: DB 0 ;Emphasized mode flag DB 0 ;Condensed mode flag DB 0 ;Expanded mode flag DB 0 ;Double strike mode flag ; ; DS 20 STACK: DB 2 ;Always use a stack FIN: ; FONT: ;The download font follows DB 1BH, 26H, 00H ;Code to cause the Epson to accept font DB FFCHAR ;First font character DB LFCHAR ;Last font character ; ; The font to be downloaded is appended to this file. FXDRVR expects ; exactly 3072 bytes here and that is the number that will be ; transmitted to the FX-80. ; DB '********' ;To make finding the end-of-program DB '********' ; easier. ; END