;----------------------------------------------------------------------- ; PROGRAM PLOT ;----------------------------------------------------------------------- ; ;THIS PROGRAM READS A SEQUENTIAL PLOT COMMAND FILE, MAKES A MEMORY IMAGE ;OF THE PLOT, AND PRINTS THE PLOT ON THE PRINTER ; ; COPYRIGHT (C) 1984 BY THOMAS E. SPEER. ALL RIGHTS RESERVED ; 887 BRIDDLEWOOD LN. ; DAYTON, OHIO 45430 ; THIS PROGRAM IS RELEASED TO THE PUBLIC DOMAIN FOR ; NON-COMMERCIAL USE ONLY. ; ; ;REVISION HISTORY ; ; VERSION 3.3 31 JUL 84 T. SPEER ; FIXED BUG IN OKI VERSION OF PRESET ROUTINE. EXTRANEOUS EXIT ; GRAPHICS COMMAND WAS BEING SENT. ; ; VERSION 3.3 7 JUL 84 T. SPEER ; ADDED TEXT COMAND. ADDED QUIT TO PROPERLY CLOSE OUTPUT FILE. ; MODIFIED GBUFOUT TO SKIP TOTALLY BLANK LINES. ; ; VERSION 3.2B 27 JUN 84 T. SPEER ; CROSS HATCHED COLOR PATTERNS FINE TUNED. ADDED BLINKING ; STATUS MESSAGE. SPECIAL PATTERNS CORRECTED. ALL SUBROUTINES ; PLACED IN ALPHABETICAL ORDER. ; ; VERSION 3.2A 18 JUN 84 T. SPEER ; COLOR PATTERNS CHANGED. 15 SPECIAL PATTERNS ADDED FROM ; 49 TO 63. THESE MAKE IT EASIER TO MATCH PATTERNS FROM ; OTHER SYSTEMS. THE DEFAULT PATTERNS SUPPLIED ARE THE SAME ; AS USED FOR NMOS AND CMOS VLSI CIF PLOTS. ; ; VERSION 3.2 28 MAR 84 T. SPEER ; CITOH MODIFICATIONS DEBUGGED. IDS MODS REMOVED (SAME AS OKI) ; BASE2 MODS REMOVED (UNTESTED- NOT SUITABLE FOR RELEASE) ; ; VERSION 3.2 3 FEB 84 T. SPEER ; THIS VERSION ADDS THE PATTERNED ERASE, THE UPLOAD (COLOR ; CODES), AND EXTEND COMMANDS. ; ; VERSION 3.1 10 DEC 83 T. SPEER ; ADDED PATTERN FILLS AND LINES USING A CROSS-HATCHED METHOD AND ; AN ORDERED DITHER MATRIX METHOD. ; ; VERSION 3.0 5 NOV 83 T. SPEER ; THIS VERSION READS ALL X AND Y COORDINATES AS ; 2 BYTE FIXED POINT NUMBERS (16 BIT SIGNED VALUES BETWEEN 0 AND 1) ; ; COORDINATES MUST BE BETWEEN 0.0 AND 1.0 TO LIE ON PLOT. THIS ; MAKES THE PLOT DEVICE INDEPENDENT. THE FIXED POINT VALUES ARE EASILY ; CREATED BY THE HIGH LEVEL PROGRAM BY MULTIPLYING THE COORDINATES BY ; 32767 AND TRUNCATING TO AN INTEGER. ; ; VERSION 2.0 T. SPEER ; THIS VERSION USED 32 BIT FLOATING POINT INTEGERS WITH A FORTRAN ; ROUTINE PATCHED IN TO DO THE CONVERSION TO INTEGER RASTER COORD. ; ; VERSION 1.0 T. SPEER ; THIS VERSION USED 16 BIT INTEGER COORDINATES THAT WERE TIED TO ; THE EPSON MX-80 RESOLUTION. NO CONVERSION WAS REQUIRED. ; ;----------------------------------------------------------------------- ; ORG 100H ;BEGINNING OF TPA MVI C,09H ;SELECT PRINT FUNCTION LXI D,BANNER ;PRINT BANNER MESSAGE CALL FDOS ; JMP ENTRY ;JUMP AROUND VARIABLE STORAGE AREA BANNER: DB ' PLOT Version 3.3 31/7/84',0DH,0AH DB ' (c) by T. E. Speer',0DH,0AH,0AH,'$' DB ' All Rights Reserved',0DH,0AH,0DH,0AH,'$' ; ; ; ;========================= PRINTER FLAGS ================================== ;SET THE ONE THAT MATCHES YOUR PRINTER TO TRUE, AND SET THE OTHERS TO FALSE. ; TRUE EQU 0FFFFH FALSE EQU NOT TRUE EPSON EQU TRUE ;FLAG FOR EPSON MX-80 WITH GRAPHTRAX CITOH EQU FALSE ;FLAG FOR CITOH, PROWRITER, ETC OKI EQU FALSE ;FLAG FOR OKIDATA ;IDS SET OKI FLAG TO TRUE- IDS PRINTERS ACT SAME AS OKI ;GEMINI 10 SET EPSON FLAG TO TRUE- GEMINI 10 ACTS SAME AS EPSON ;NEC SET CITOH FLAG TO TRUE- NEC ACTS SAME AS CITOH ;APPLE DOT MATRIX - ACTS SAME AS CITOH, BUT SOME SEQUENCES DIFFER. ; SET CITOH FLAG TO TRUE AND CHECK SEQUENCES AT ESCK, ; AND IN LN772 AND PRESET SUBROUTINES. ; ;====================== PRINTER PARAMETERS =============================== ; THIS SECTION SETS THE SPECIFIC CONSTANTS FOR YOUR PRINTER. ; ;***** NOTE ***** THE MAXIMUM VALUE FOR MAXX THAT CAN BE USED IS 1530. ; THE MAXIMUM VALUE FOR MAXY THAT CAN BE USED IS 1785. THESE LIMITS ; ARE REQUIRED TO AVOID ARITHMETIC OVERFLOWS. ; THE SIZE OF THE MAP ( (MAXX+1)*(MAXY+1)/7 ) MUST FIT BETWEEN THE END OF ; THE PROGRAM AND THE END OF THE TPA. ; ; PRINTERS SEEM TO HAVE TWO BASIC METHODS OF GOING INTO GRAPHICS ; MODE. THE EPSON AND CITOH PRINTERS USE AN SEQUENCE ; FOLLOWED BY A SPECIFIED NUMBER OF GRAPHICS BYTES. THE OKIDATA AND IDS ; PRINTERS USE AN TO TOGGLE INTO GRAPHICS MODE, AND THEN REMAIN ; IN GRAPHICS UNTIL AN IS RECEIVED. ; THE BASIC PHILOSOPHY ADOPTED HERE IS TO APPEND THE ; SEQUENCE AND THE NUMBER OF BYTES (IF REQUIRED) TO THE HEAD OF THE ; GRAPHICS OUTPUT BUFFER FOR THOSE PRINTERS IN THE FIRST GROUP. PRINTERS ; IN THE SECOND GROUP ARE HANDLED BY PUTTING THE COMMANDS IN THE ; GBUFOUT ROUTINE. ALL PRINTERS ARE KEPT IN NORMAL TEXT MODE, EXCEPT ; WHEN ACTUALLY PRINTING GRAPHICS. ; IF EPSON MAXX EQU 479 ;SET MAXIMUM WIDTH TO EPSON LOW RES MODE MAXY EQU 573 ;SET MAXIMUM HEIGHT TO MAKE SQUARE PLOT MAPSIZE EQU 39360D ;TOTAL SIZE OF MAP CWIDTH EQU 6 ;RASTER WIDTH OF A PRINTED CHARACTER NO8BIT EQU FALSE ;SET TO FALSE IF YOUR INTERFACE CAN MSBTOP EQU TRUE ;MOST SIG. BIT IS TOP OF STROKE ; SET UP GRAPHIC OUTPUT BUFFER AREA ESCK DB 1BH,'K' ;DEFINE ESC "K" CHARACTER SEQUENCE NGRAPH DW 0000H ;INITIALIZE GRAPHIC COUNTER GBUFF DS MAXX+1 ;SET ASIDE AREA FOR GRAPHIC O/P BUFFER ENDIF ;(EPSON) ; IF CITOH MAXX EQU 636 ;SET MAXIMUM WIDTH FOR 80 DOTS/INCH MODE MAXY EQU 573 ;SET MAXIMUM HEIGHT TO MAKE SQUARE PLOT MAPSIZE EQU 52234D ;TOTAL SIZE OF MAP CWIDTH EQU 8 ;RASTER WIDTH OF A PRINTED CHARACTER NO8BIT EQU FALSE ;SET TO FALSE EVEN IF 7 BIT INTERFACE MSBTOP EQU FALSE ;LEAST SIG. BIT IS TOP DOT OF STROKE ; SET UP GRAPHIC OUTPUT BUFFER AREA ESCK: DB 1BH,'S',0,0,0,0 ;GRAPHIC MODE SELECT CODE GBUFF: DS MAXX+1 ;SET ASIDE AREA FOR GRAPHIC O/P BUFFER NGRAPH DW 0000H ;INITIALIZE GRAPHIC COUNTER ENDIF ;(CITOH) ; IF OKI MAXX EQU 575 ;SET MAXIMUM WIDTH FOR 72 DOTS/INCH MAXY EQU 573 ;SET MAXIMUM HEIGHT TO MAKE SQUARE PLOT MAPSIZE EQU 47232D ;TOTAL SIZE OF MAP CWIDTH EQU 6 ;RASTER WIDTH OF CHARACTER NO8BIT EQU FALSE ;SHOULD BE FALSE EVEN IF 7 BIT INTERFACE MSBTOP EQU FALSE ;LEAST SIG. BIT IS TOP DOT OF STROKE ; SET UP GRAPHIC OUTPUT BUFFER AREA GBUFF: DS MAXX+1 NGRAPH DW 0000H ENDIF ;(OKI) ; ; ;========================= DATA STORAGE SECTION ============================ ; COLOR DB 0 XPOS DW 0 YPOS DW 0 X DW 0 Y DW 0 YFILL DW 0 NCHAR DW 0 ACHAR DB 40H POINTER DB 128D ;POINTER IN FILE BUFFER POINTR2 DB 00H ;POINTER IN OUTPUT FILE BUFFER OLDSTK DW 0000H STACK DS 80H ;SET ASIDE 128 LEVEL STACK XDOT DW 0000H ;POSITION OF DOT TO BE PLOTTED YDOT DW 0000H ;POSITION OF DOT TO BE PLOTTED XYADDR DW ORIGIN ;ADDRESS OF X,Y LOCATION XYBIT DB 00H ;BIT IN BYTE @ XYADDR FOR X,Y DIVDND DW 0000H ;2 BYTE DIVIDEND IN DIVIDE DIVSOR DB 00H ;1 BYTE DIVISOR IN DIVIDE QOTENT DB 00H ;1 BYTE QUOTIENT FROM DIVIDE RMANDR DB 00H ;1 BYTE REMAINDER FROM DIVIDE BLANK EQU ' ' NOSPEC DB 'No File Specified',0DH,0AH,'$' ;ERROR MESSAGES NOFILE DB 'File Not Found',0DH,0AH,'$' EOFMSG DB 'End of File',0DH,0AH,'$' NODIR DB 'No Directory Space Available',0DH,0AH,'$' NOROOM DB 'Disk is Full',0DH,0AH,'$' UNKNCH DB 'Undefined Command Character Encountered',0DH,0AH,'$' STAT1 DB ' Working ... ',0DH,'$' STAT2 DB ' ... Working ',0DH,'$' STAT3 DB ' Printing Picture ',07H,0DH,'$' STATNO DB 00H DELTAX DW 0000H ;LOCAL VARIABLES FOR INCPLT DELTAY DW 0000H ;LOCAL VARIABLES FOR INCPLT EPSLNX DW 0000H ;LOCAL VARIABLES FOR INCPLT EPSLNY DW 0000H ;LOCAL VARIABLES FOR INCPLT SX DW 0000H ;LOCAL VARIABLES FOR INCPLT SY DW 0000H ;LOCAL VARIABLES FOR INCPLT DELTA3 DW 0000H ;LOCAL VARIABLES FOR INCPLT NI DW 0000H ;LOCAL VARIABLES FOR INCPLT ; CMASK DB 0FFH ;COLOR MASK PATRN DS 8 ;CELL STORAGE FOR CLRMAP (ERASE) PLAIDS DB 00H,01H,71H,13H,05H,0FH,35H,11H ; CROSS HATCHED PATTERNS ; CIFPAT DB 00H, 03H, 48H, 03H, 00H, 30H, 84H, 30H ;ND DB 00H,0CCH, 00H,0CCH, 00H, 00H, 00H, 00H ;NI S DB 08H, 04H, 02H, 01H, 80H, 40H, 20H, 10H ;NT P DB 11H, 30H, 71H, 30H, 11H, 03H, 17H, 03H ;NC E DB 22H, 00H, 88H, 00H, 22H, 00H, 88H, 00H ;NM C DB 0C0H, 81H, 03H, 06H, 03H, 81H,0C0H, 60H ;NB P I DB 1CH, 3EH, 36H, 3EH, 1CH, 00H, 00H, 00H ;NG A A DB 00H, 00H, 00H, 00H, 00H, 00H, 00H, 01H ;CW T L DB 04H, 11H, 04H, 00H, 40H, 11H, 40H, 00H ;CD T DB 02H, 04H, 08H, 10H, 20H, 40H, 80H, 01H ;CP E DB 00H, 00H, 10H, 38H, 10H, 00H, 00H, 00H ;CS R DB 66H, 99H, 99H, 66H, 66H, 99H, 99H, 66H ;CC N DB 00H, 00H, 80H, 10H, 00H, 00H, 10H, 80H ;CM S DB 81H,0C3H, 66H, 66H,0C3H, 81H, 00H, 00H ;CG DB 0FH, 0EH, 0CH, 08H, 00H, 00H, 00H, 00H ;CE ; DITHARR DB 63, 95, 71, 103, 65, 97, 73, 105 ; ORDERED DB 111, 79, 119, 87, 113, 81, 121, 89 ; DB 75, 107, 67, 99, 77, 109, 69, 101 ; DITHER DB 123, 91, 115, 83, 125, 93, 117, 85 ; DB 66, 98, 74, 106, 64, 96, 72, 104 ; MATRIX DB 114, 82, 122, 90, 112, 80, 120, 88 ; DB 78, 110, 70, 102, 76, 108, 68, 100 ; DB 126, 94, 118, 86, 124, 92, 116, 84 ; ; ; ; ; BOOT EQU 0000H ;CP/M SYSTEM ENTRY POINT FCB EQU BOOT+005CH ;LOCATION OF FILE CONTROL BLOCK DMA EQU BOOT+0080H ;FILE BUFFER ADDRESS FDOS EQU BOOT+0005H ;ENTRY POINT FOR CPM FUNCTIONS FCB2 DS 33D ;OUTPUT FILE CONTROL BLOCK DMA2 DS 128D ;OUTPUT FILE BUFFER OPDISK DB 00H ;OUTPUT TO DISK FLAG ; ;----------------------------------------------------------------------- ; ENTRY LXI SP,STACK+80H ;SET NEW 128 LEVEL STACK LDA FCB+9 ;GET FIRST CHARACTER OF FILE TYPE CPI BLANK ;IS TYPE BLANK? JNZ NAME ;NO- TYPE HAS BEEN SPECIFIED MVI A,'V' ;MAKE DEFAULT TYPE "VEC" STA FCB+9 ;STORE DEFAULT IN FILE TYPE AREA MVI A,'E' STA FCB+10 ;STORE DEFAULT IN FILE TYPE AREA MVI A,'C' STA FCB+11 ;DONE- DEFAULT IS SET NAME LDA FCB+1 ;GET FIRST CHAR FROM FCB CPI BLANK ;IS NAME BLANK? JNZ OPENOP ;JUMP IF A FILE NAME EXISTS MVI C,09H ;SELECT PRINT STRING FUNCTION LXI D,NOSPEC ;PASS ERROR MESSAGE CALL FDOS ;PRINT IT JMP BOOT ;RETURN TO CPM SYSTEM LEVEL OPENOP LDA FCB+17D ;GET 1ST CHAR OF O/P FILE CPI BLANK ;IS NAME BLANK? JZ OPENFIL ;BLANK= NORMAL PRINT OUTPUT MVI A,01H ;SET O/P FILE FLAG=1 (DISK O/P) STA OPDISK ;STORE FLAG ; ; MOVE O/P FILE NAME TO NEW FCB ; MVI C,16D ;HALF OF FCB#1 IS O/P INFO LXI D,006CH ;START OF O/P FILE NAME LXI H,FCB2 ;SET DESTINATION ADDRESS MOVFCB LDAX D ;GET NAME CHARACTER MOV M,A ;STORE NAME CHARACTER INX D ;INCREMENT OLD NAME ADDRESS INX H ;INCREMENT NEW NAME ADDRESS DCR C ;DECREMENT COUNTER JNZ MOVFCB ;LOOP BACK IF NOT DONE ; MVI A,0 ;CLEAR ACCUMULATOR STA FCB2+32D ;ZERO CR FIELD IN O/P FCB ; LDA FCB2+9 ;GET 1ST CHAR IN O/P FILE TYPE CPI BLANK ;IS FILE TYPE BLANK? JNZ DELETE ;NOT BLANK- GO TO DELELTE OLD MVI A,'P' ;MAKE DEFAULT 'PLT' STA FCB2+9 ;STORE DEFAULT 'P' MVI A,'L' STA FCB2+10 ;STORE DEFAULT 'L' MVI A,'T' STA FCB2+11 ;STORE DEFAULT 'T' ; DELETE LXI D,FCB2 ;PASS O/P FILE FCB MVI C,19D ;SELECT DELETE FUNCTION CALL FDOS ;DELETE OLD FILE ; ; MAKE NEW O/P FILE ; MVI C,26D ;SELECT SET DMA FUNCTION LXI D,DMA2 ;PASS O/P FILE BUFFER ADDRESS CALL FDOS ;SET DMA ADDRESS ; MVI C,22D ;SELECT MAKE FILE FUNCTION LXI D,FCB2 ;PASS FCB FOR O/P CALL FDOS ;MAKE NEW FILE CPI 0FFH ;IS DIRECTORY FULL? JNZ OPENFIL ;NO- GO ON WITH PROGRAM ; MVI C,09H ;SELECT PRINT FUNCTION LXI D,NODIR ;PASS NO DIRECTORY SPACE MSG CALL FDOS ;PRINT ERROR MESSAGE JMP BOOT ;FATAL ERROR- QUIT ; ;OPEN DISK FILE OF PLOT COMMANDS ; OPENFIL MVI C,26D ;SELECT SET DMA FUNCTION LXI D,DMA ;PASS I/P BUFFER LOCATION CALL FDOS ;SET DMA TO I/P BUFFER ; MVI C,0FH ;SELECT OPEN FILE FUNCION MVI A,00H ;CLEAR ACCUMULATOR STA FCB+12 ;CLEAR EXTENT COUNTER STA FCB+14 ;CLEAR S2 PARAMETER IN FCB LXI D,FCB ;PASS FCB CALL FDOS ;OPEN FILE CPI 0FFH ;WAS FILE FOUND? JNZ REWIND ;IF FILE EXITS, REWIND IT MVI C,09H ;SELECT PRINT FUNCTION LXI D,NOFILE ;PASS MESSAGE CALL FDOS ;PRINT IT JMP BOOT ;RETURN TO CPM COMMAND LEVEL ; REWIND MVI A,00H ;CLEAR ACCUMULATOR STA FCB+32D ;REWIND BY SETTING RECORD#=0 ; PARSE CALL BYTE ;GET COMMAND CHARACTER CPI 60H ;IS IT LOWER CASE? JC PARSE0 ;NO, SO SKIP SHIFTING IT XRI 00100000B ;SHIFT CHARACTER TO UPPER CASE ; PARSE0 CPI 'P' ;IS IT A "P"? PUSH PSW ;SAVE COMMAND CHARACTER CZ POINT ;P COMMANDS PLOT POINT POP PSW JZ PARSE ;LOOP BACK FOR NEW CHAR ; CALL STAT ;DISPLAY STATUS MESSAGE ; ; CPI 'C' PUSH PSW CZ COLOUR ;C COMMANDS SET COLOR POP PSW JZ PARSE ;LOOP BACK FOR NEW CHAR ; CPI 'D' ;IS IT A "D"? PUSH PSW ;SAVE COMMAND CHARACTER CZ PLOTSEG ;D COMMANDS PLOT SEGMENT POP PSW JZ PARSE ;LOOP BACK FOR NEW CHAR ; CPI 'E' PUSH PSW CZ CLRMAP ;E COMMANDS CLEAR MEMORY MAP TO COLOR POP PSW JZ PARSE ;LOOP BACK FOR NEW CHAR ; CPI 'F' PUSH PSW CZ FILL ;F COMMANDS FILL AREA TO COLOR POP PSW JZ PARSE ;LOOP BACK FOR NEW CHARACTER ; CPI 'I' PUSH PSW CZ INCPLT ;I COMMANDS PLOT INCREMENTAL SEGMENT POP PSW JZ PARSE ;LOOP BACK FOR NEW CHAR ; CPI 'M' ;M COMMANDS MOVE TO COORD W/O PLOTTING PUSH PSW CZ MOVE POP PSW JZ PARSE ; CPI 'N' JZ PARSE ;N COMMANDS A NO OPERATION LOOP ; CPI 'O' PUSH PSW CZ MAPOUT ;O COMMANDS PRINTING OF PLOT POP PSW JZ PARSE ;LOOP BACK FOR NEW CHAR ; CPI 'Q' PUSH PSW CZ QUIT ;Q COMMANDS TERMINATION OF PROGRAM POP PSW JZ PARSE ;LOOP BACK FOR NEW CHAR ; CPI 'S' PUSH PSW CZ STRING ;S COMMANDS CHARACTER STRING PLOTTING POP PSW JZ PARSE ;LOOP BACK FOR NEW CHAR ; CPI 'T' PUSH PSW CZ TEXT ;T COMMANDS RAW TEXT OUTPUT POP PSW JZ PARSE ;LOOP BACK FOR NEW CHAR ; CPI 'U' PUSH PSW CZ UPLOAD ;U COMMANDS UPLOAD OF COLOR PATERNS POP PSW JZ PARSE ;LOOP BACK FOR NEW CHAR ; CPI 'X' PUSH PSW CZ XTEND ;PROVISION FOR NON-STANDARD COMMANDS POP PSW JZ PARSE ;LOOP BACK FOR NEW CHAR ; CPI 0DH ;IGNORE CARRIAGE RETURNS JZ PARSE ; CPI 0AH JZ PARSE ;IGNORE LINE FEEDS ; ; COMMAND CHARACTER DOES NOT MATCH ANY DEFINED COMMAND ; MVI C,09H ;SELECT PRINT STRING FUNCTION LXI D,UNKNCH ;PASS UNDEFINED CHARACTER MESSAGE CALL FDOS ;PRINT IT JMP PARSE ;LOOP UP TO TOP TO GET NEW CHARACTER ; ;----------------------------------------------------------------------- ; DEFINE SUBROUTINES ;----------------------------------------------------------------------- ; ; CONVERT BINARY INTEGER TO DECIMAL ASCII NUMBER ; ; INPUTS: ; N (BINARY NUMBER) IN [DE] ; ADDRESS TO STORE LOW DIGIT IN [HL] ; OUTPUTS: ; ASCII NUMBER STORED IN MEMORY, HIGH BYTE FIRST. ; NOTE: THE ADDRESS IS DECREMENTED FOR EACH CHAR. ; REGISTER STATUS: ; ALL REGISTER VALUES PRESERVED ; ERROR CONDITIONS: ; NONE ; IF CITOH BINDEC: PUSH H ;SAVE REGISTERS PUSH D PUSH B PUSH PSW ; MVI A,10D ;GET A TEN STA DIVSOR ;DIVISIONS WILL BE BY BASE 10 ; BDECLP: PUSH H ;SAVE ADDRESS FOR FUTURE USE MOV A,D STA DIVDND ;FIRST DIVIDE HIGH BYTE MVI A,00H STA DIVDND+1 ;16 BIT DIVIDEND NOW = 8 BIT N HIGH BYTE CALL DIVIDE ;DIVIDE BY 10 LDA QOTENT MOV D,A ;RESULT IS HIGH BYTE OF NEW N LXI H,RMANDR MOV H,M ;DIVIDE REMAINDER WITH LOW BYTE OF N MOV L,E ;ADD LOW BYTE OF N TO REMAINDER SHLD DIVDND CALL DIVIDE ;DIVIDE LOW BYTES BY 10 POP H ;RETRIEVE ADDRESS TO RECEIVE CHARACTER LDA RMANDR ;REMAINDER IS DIGIT ADI 30H ;CONVERT DIGIT TO ASCII MOV M,A ;STORE CHARACTER DCX H ;MOVE POINTER LEFT LDA QOTENT ;GET RESULT OF DIVISION MOV E,A ;RESULT IS LOW BYTE OF NEW N ORA D ;IS NEW END = 0? JNZ BDECLP ;LOOP BACK UP IF > 0 ; POP PSW POP B POP D POP H ;REGISTERS RESTORED RET ENDIF ;(CITOH) ;---------------------------------------------------------------------- ; ; BMULT PERFORMS A 1-BYTE BY 2-BYTE MULTIPLY ; ; THIS ROUTINE IS FROM ELECTRONICS MAGAZINE, FEB 24, 1982. ; BY JERRY L. GOODRICH, PENN. STATE U. ; ; INPUTS: ; 8-BIT NUMBER IN [A] ; 16-BIT NUMBER IN [BC] ; OUTPUTS: ; PRODUCT IN [A],[HL] (HIGH BYTE IN [A]) ; REGISTER STATUS: ; SEE INPUTS AND OUTPUTS ; ERROR CONDITIONS: ; NONE ; BMULT LXI H,0 ;ZERO PARTIAL PRODUCT LXI D,7 ;D=0,E=BIT COUNTER ADD A ;GET FIRST MULTIPLIER BIT LOOP1: JNC ZERO ;ZERO SKIP DAD B ;ONE-ADD MULTIPLICAND ADC D ;ADD CARRY TO THIRD BYTE OF PRODUCT ZERO: DAD H ;SHIFT PRODUCT LEFT ADC A DCR E ;DECREMENT BIT COUNTER JNZ LOOP1 ;LOOP UNTIL DONE RNC ;DONE IF NO CARRY DAD B ;OTHERWISE DO LAST ADD ADC D RET ;AND RETURN ;----------------------------------------------------------------------- ; BYTE GETS NEXT BYTE IN BUFFER ; NEXT RECORD IS READ IF NEED BE ; INPUTS: ; 128 CHARACTER BUFFER @ DMA ; CHARACTER POINTER @ POINTER WHICH IS SET @ LAST POSITION ; OUTPUTS: ; NEW BYTE IN ACCUMULATOR ; REGISTER STATUS: ; [BC],[DE],[HL] REGISTERS PRESERVED ; ERROR CONDITIONS: ; NONE- IF POINTER EXCEEDS 128, NEW RECORD IS READ ; BYTE PUSH B ;SAVE REGISTERS PUSH D PUSH H ; LDA POINTER ;GET POINTER VALUE CPI 128D ;IS POINTER=128? CZ READ ;GET RECORD IF LAST ONE WAS #128 LDA POINTER ;GET NEW POINTER VALUE INR A ;INCREMENT POINTER VALUE STA POINTER ;STORE NEW POINTER VALUE MOV C,A ;SAVE POINTER VALUE IN C MVI B,0 ;MAKE BC=C LXI H,DMA-1 ;LOAD HL WITH BYTE BEFORE DMA DAD B ;CALCULATE ADDR OF DESIRED BYTE MOV A,M ;GET BYTE ; POP H ;RESTORE REGISTERS POP D POP B RET ;DONE-- BYTE IS IN ACCUM. ;----------------------------------------------------------------------- ; ; PRINTED CHARACTER OUTPUT ; ; INPUTS: ; CHARACTER IN REGISTER [A] ; ; OUTPUTS: ; GRAPHIC BUFFER IS FLUSHED ; CHARACTER IS PUT OUT TO PRINTER ; ADDRESS IN [HL] IS INCREMENTED BY (CWIDTH - 1) ; DOT COUNTER INCREMENTED BY (CWIDTH - 1) ; THE ABOVE ARE TO ACCOUNT FOR THE SIZE OF A CHARACTER ; AS OPPOSED TO A SINGLE DOT ; REGISTER STATUS: ; [A,PSW],[BC] PRESERVED ; [DE] DECREMENTED BY (CWIDTH -1) ; [HL] INCREMENTED BY (CWIDTH -1) ; ERROR CONDITIONS: ; NONE ; CHAROUT: PUSH PSW ;SAVE REGISTERS PUSH B PUSH D PUSH H ; XRI 10000000B ;CLEAR HIGH BIT OF CHARACTER CALL GBUFOUT ;FLUSH GRAPHIC BUFFER MVI C,05H ;SELECT LIST OUTPUT MOV E,A ;PASS CHARACTER CALL PDOS ;SEND CHARACTER TO PRINTER ; POP H ;RECALL REGISTERS POP D MVI A,CWIDTH-1 CHARO1: INX H ;INCREMENT ADDRESS DCX D ;DECREMENT DOT COUNTER SUI 1 ;DECREMENT LOOP COUNTER JNZ CHARO1 ; POP B POP PSW RET ; ;----------------------------------------------------------------------- ; ; CLEAR MEMORY SUBROUTINE ; ; INPUTS: ; BITMAP OF SIZE MAPSIZE LOCATED AT ORIGIN ; MAP COLOR STORED IN COLOR ; (POS = PATTERNED, 0 = WHITE, - = COMPLEMENTARY) ; OUTPUTS: ; ENTIRE MAP AREA SET TO DESIRED COLOR OR PATTERN ; REGISTERS: ; ALL REGISTER VALUES DESTROYED ; ERROR CONDITIONS: ; NONE ; CLRMAP: LDA COLOR ;GET COLOR ORA A ;SET FLAGE ACCORDING TO COLOR JNZ CLRNZ ;IS COLOR NON-WHITE? LXI D,MAPSIZE ;PUT MAPSIZE IN [DE] AS COUNTER LXI H,ORIGIN ;PUT START OF MAP IN [HL] MVI C,00H ;C CONTAINS IMAGE OF WHITE BYTE CLRLP1: MOV M,C ;TOP OF LOOP, STORE BYTE INX H ;INCREMENT ADDRESS IN MAP DCX D ;DECREMENT LOOP COUNTER MOV A,D ;MOVE HIGH BYTE OF COUNT. TO [A] ORA E ;CHECK FOR 0 COUNTER JNZ CLRLP1 ;LOOP UNTIL DONE RET ;FINISHED WITH WHITE ERASE ; CLRNZ: PUSH PSW ;SAVE FLAG VALUES ; NOW FORM 8 BYTE COLOR PATTERN LXI H,PATRN+7 ;POINT TO LAST IN PATTERN SEQUENCE MVI C,07H ;INITIALIZE X COUNTER CLRLP2: MVI D,80H ;SET UP Y BIT SELECT MVI E,07H ;INITIALIZE Y COUNTER MVI B,00H ;INITIALIZE PATTERN CLRLP3: CALL CLRMSK ;FORM COLOR MASK BASED ON X,Y LDA CMASK ;GET MASK ANA D ;SELECT ONE BIT ORA B ;ADD BIT TO PATTERN MOV B,A ;SAVE NEW PATTERN MOV A,D ;MODIFY BIT SELECT MASK RRC ;MOVE SELECT BIT DOWN ONE NOTCH MOV D,A ;SAVE NEW BIT SELECT DCR E ;DECREMENT Y COUNTER JP CLRLP3 ;JUMP BACK IF NOT NEGATIVE (NEED 0 PASS) POP PSW ;RETRIEVE COLOR CODE FLAG SETTINGS PUSH PSW ;RE-SAVE FLAGS SETTINGS JP CLRL31 ;POSITIVE FLAG MEANS PATTERN IS OK MOV A,B ;GET PATTERN CMA ;COMPLEMENT PATTERN FOR NEGATIVE COLORS MOV B,A ;STORE PATTERN BYTE CLRL31: MOV M,B ;SAVE PATTERN FOR THIS X LOCATION DCX H ;MOVE MEMORY POINTER OVER DCR C ;DECREMENT X COORDINATE/COUNTER JP CLRLP2 ;ONLY DONE WHEN NEGATIVE (NEED 0 PASS) ; ; SET UP FOR CLEARING MEMORY ; ROTATE ARRAY OF PATTENRX DOWN TO MATCH ; LXI B,(MAXY+1) MOD 8+1;COUNTER FOR ROTATIONS DUE TO MISMATCH CLRLP4: CALL ROTPAT ;ROTATE PATTERN ARRAY 1 POSITION DCR C ;DECREMENT COUNTER JNZ CLRLP4 ;LOOP BACK IF NOT DONE ; LXI H,ORIGIN ;SET MAP POINTER TO START OF MAP LXI B,(MAXY+1)/7 ;INITIALIZE LINE COUNTER CLRLP5: LXI D,(MAXX+1)/8 ;INITALIZE DOT COUNTER CLRL51: LDA PATRN ;GET FIRST BYTE ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER LDA PATRN+1 ;GET SECOND BYTE ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER LDA PATRN+2 ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER LDA PATRN+3 ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER LDA PATRN+4 ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER LDA PATRN+5 ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER LDA PATRN+6 ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER LDA PATRN+7 ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER DCX D ;DECREMENT X COUNTER MOV A,E ORA D ;IS COUNTER ZERO? JNZ CLRL51 ;LOOP BACK UNTIL DONE ; LXI D,(MAXX+1)MOD 8 ;SET COUNTER FOR REST OF LINE MOV A,D ;CHECK TO SEE IF LINESIZE ID MULT OF 8 ORA E ;WAS MOD 8 =0? JZ CLRLP6 ;JUMP TO BOTTOM OF LOOP IF FINISHED LDA PATRN ;APPLY PATTERN TO REMANING 1-7 BYTES ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER DCX D ;DECREMENT LINE LENGTH COUNTER MOV A,E ORA D ;IS COUNTER = 0? JZ CLRLP6 ;IF FINISHED, SKIP TO BOTTOM OF OUTER LP LDA PATRN+1 ;CONTINUE WITH NEXT PATTERN BYTE ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER DCX D ;DECREMENT LINE LENGTH COUNTER MOV A,E ORA D ;IS COUNTER = 0? JZ CLRLP6 ;IF FINISHED, SKIP TO BOTTOM OF OUTER LP LDA PATRN+2 ;CONTINUE WITH NEXT PATTERN BYTE ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER DCX D ;DECREMENT LINE LENGTH COUNTER MOV A,E ORA D ;IS COUNTER = 0? JZ CLRLP6 ;IF FINISHED, SKIP TO BOTTOM OF OUTER LP LDA PATRN+3 ;CONTINUE WITH NEXT PATTERN BYTE ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER DCX D ;DECREMENT LINE LENGTH COUNTER MOV A,E ORA D ;IS COUNTER = 0? JZ CLRLP6 ;IF FINISHED, SKIP TO BOTTOM OF OUTER LP LDA PATRN+4 ;CONTINUE WITH NEXT PATTERN BYTE ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER DCX D ;DECREMENT LINE LENGTH COUNTER MOV A,E ORA D ;IS COUNTER = 0? JZ CLRLP6 ;IF FINISHED, SKIP TO BOTTOM OF OUTER LP LDA PATRN+5 ;CONTINUE WITH NEXT PATTERN BYTE ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER DCX D ;DECREMENT LINE LENGTH COUNTER MOV A,E ORA D ;IS COUNTER = 0? JZ CLRLP6 ;IF FINISHED, SKIP TO BOTTOM OF OUTER LP LDA PATRN+6 ;CONTINUE WITH NEXT PATTERN BYTE ANI 7FH ;CLEAR HI BIT MOV M,A ;STORE PATTERN IN MEMORY MAP INX H ;MOVE MEMORY POINTER ; CLRLP6: CALL ROTPAT ;ROTATE PATTERN DOWN TO MATCH CELLS DCX B ;BOTTOM OF OUTER LOOP. DEC LINE COUNTER MOV A,C ORA B ;IS COUNTER = 0? JNZ CLRLP5 ;LOOP BACK UP FOR ANOTHER IF REQ'D ; POP PSW ;CLEAN UP STACK RET ; ;----------------------------------------------------------------------- ; ; COLOR MASK ; ; THIS SUBROUTINE FORMS THE COLOR MASK USED IN PLOTTING POINTS ; ; METHOD: ; THE PLOT IS DIVIDED UP INTO 8 X 8 RASTER CELLS. ; FOR COLOR VALUES BETWEEN 1 AND 63, THE CELL IS COMPOSED ; OF AN X PATTERN AND A Y PATTERN WHICH ARE XOR'ED WITH ; EACH OTHER TO FORM A "PLAID" PATTERN ; FOR COLOR VALUES 64 AND ABOVE, ORDERED DITHERING IS USED ; ORDERED DITHERING IS A TECHNIQUE IN WHICH THE DOTS IN ; THE CELL ARE ADDED IN IN A PRE-ARRANGED POSITION BASED ; UPON THE "INTENSITIY" OF THE CELL. THE INTERSECTION OF ; THE POINT AND THE PATTERN (STORED IN THE ARRAY "DITHARR" ; DETERMINES WHETHER OR NOT THE POINT IS PLOTTED ; ; FOR BOTH METHODS, A COLOR MASK IS CREATED, WHICH IS ; ALL 1'S IF THE POINT IN THE PATTERN PLANE IS ON, OR ; ALL 0'S IF THE POINT IN THE PATTERN PLANE IS OFF. ; INPUTS: ; X COORDINATE IN BC ; Y COORDINATE IN DE ; OUTPUTS: ; COLOR MASK STORED IN CMASK ; REGISTER STATUS: ; ALL REGISTERS PRESERVED ; ERROR CONDITIONS: ; NONE ; CLRMSK PUSH PSW ;SAVE REGISTERS PUSH B PUSH D PUSH H ; MOV A,C ;FORM X CELL COORDINATE ANI 00000111B MOV B,A ; MOV A,E ;FORM Y CELL COORDINATE ANI 00000111B MOV C,A ; LDA COLOR ;GET COLOR CODE ORA A ;SET FLAGS BASED ON BASIC CODE JZ WHTMSK ;ZERO COLOR => WHITE MASK JP POSCLR ;COLOR CODE IS POSITIVE CMA ;COMPLEMENT COLOR ADI 01H ;COLOR CODE IS NOW POSITIVE POSCLR CPI 64D ;IS COLOR CODE < 64 JNC DITHER ;CODE >=64 --> DITHERED CPI 49D ;IS COLOR CODE < 49 JNC SPECIAL ;CODE FROM 49 TO 63 --> CIFPAT'S ELSE PLAID ; PUSH PSW ;SAVE COLOR CODE ANI 07H ;SELECT LOWER 3 BITS OF COLOR CODE LXI H,PLAIDS ;GET BASE ADDRESS OF BASIC PATTERN ADD L ;ADD X CODE TO BASE ADDR TO FIND PATTERN MOV L,A MOV A,H ACI 00H ;ADD CARRY TO HIGH BYTE OF ADDRESS MOV H,A MOV A,M ;GET X PATTERN FOR CELL INR B ;INCREMENT X COORDINATE TO BE COUNTER XCELLP RAR ;ROTATE PATTERN BIT INTO CARRY DCR B ;DECREMENT COUNTER JNZ XCELLP ;LOOP BACK IF NOT DONE MVI A,0FFH ;CARRY --> PATTERN BIT SAYS PLOT POINT JC SAVXMSK MVI A,00H SAVXMSK MOV B,A ;REPLACE X CELL COORD WITH X COLOR MASK ; POP PSW ;RETRIEVE COLOR CODE ANI 38H ;SELECT 2ND 3 BITS FOR Y CODE RRC ;ROTATE BITS TO LOW ORDER POSITION RRC RRC LXI H,PLAIDS ;GET BASE ADDRESS OF BASIC PATTERN ADD L ;ADD X CODE TO BASE ADDR TO FIND PATTERN MOV L,A MOV A,H ACI 00H ;ADD CARRY TO HIGH BYTE OF ADDRESS MOV H,A MOV A,M ;GET Y PATTERN FOR CELL INR C ;INCREMENT Y COORDINATE TO BE COUNTER YCELLP RAR ;ROTATE PATTERN BIT INTO CARRY DCR C ;DECREMENT COUNTER JNZ YCELLP ;LOOP BACK IF NOT DONE MVI A,0FFH ;DOT WILL BE PLOTTED IF CARRY SET JC SAVYMSK MVI A,00H SAVYMSK XRA B ;FINAL COLOR MASK-- X PATRN XOR Y PATRN STA CMASK ;SAVE COLOR MASK ; POP H ;RESTORE REGISTERS POP D POP B POP PSW RET ;FINISHED -END OF PLAID BRANCH ; DITHER PUSH PSW ;SAVE COLOR CODE FOR FUTURE USE MOV A,C ;MULTIPLY Y CELL COORDINATE BY 8 RLC RLC RLC ADD B ;OFFSET INTO DITHER TABLE = Y*8 + X LXI H,DITHARR ;GET BASE ADDRESS OF TABLE ADD L ;ADD OFFSET TO BASE ADDRESS MOV L,A MOV A,H ACI 00H ;ADD CARRY TO HIGH BYTE MOV H,A MOV A,M ;GET DITHER TABLE VALUE POP D ;RETRIEVE COLOR CODE (FORMERLY IN [A]) CMP D ;IS DITHER VALUE > COLOR CODE? MVI A,0FFH ;CARRY--> PLOT POINT JC SAVMSK MVI A,00H ;CARRY NOT SET--> DON'T PLOT POINT SAVMSK STA CMASK ;STORE MASK FOR FUTURE USE ; POP H POP D POP B POP PSW ;REGISTERS RESTORED, STACK CLEANED UP RET ; ; SPECIAL:SUI 49D ;CODE IS NOW RELATIVE TO 49 RLC ;CODE * 8 RLC RLC ADD B ;ADD X COORD TO FORM OFFSET INTO ARRAY LXI H,CIFPAT ;GET FWA OF PATTERN ARRAY ADD L ;ADD OFFSET TO FWA MOV L,A MOV A,H ACI 00H ;ADD CARRY TO HI BYTE MOV H,A ;ADDITION COMPLETE MOV A,M ;GET PATTERN BYTE FOR THIS X COORD. INR C ;INCREMENT Y COORD TO FORM COUNTER SPCLP: RAR ;ROTATE PATTERN BIT INTO CARRY DCR C ;DECREMENT COUNTER JNZ SPCLP ;LOOP BACK UNTIL DONE MVI A,0FFH ;DOT WILL BE PLOTTED IF CARRY SET JC SAVMSK MVI A,00H ;CARRY NOT SET- DON'T PLOT POINT JMP SAVMSK ; ; WHTMSK MVI A,0FFH ;FOR WHITE, ALWAYS MODIFY DOT JMP SAVMSK ;SAVE MASK AND RETURN ; ;----------------------------------------------------------------------- ; ; DEFINE COLOR SUBROUTINE ; ; INPUTS: ; BUFFER @ DMA ; OUTPUTS: ; COLOR VALUE SAVED FOR FUTURE REFERENCE ; REGISTER STATUS: ; ALL REGISTER VALUES DESTROYED ; ERROR CONDTIONS: ; NONE ; COLOUR: CALL BYTE ;GET COLOR VALUE STA COLOR ;SAVE IT RET ; ;----------------------------------------------------------------------- ; ; THIS SUBROUTINE COMPUTES THE NEXT POINT IN A LINE SEGMENT ; MUST BE USED WITH SEGINIT TO INITIALIZE ALL VARIABLES FIRST. ; ; INPUTS: ; NI COUNTER USED BY CALLING SUB. TO KNOW WHEN DONE. ; XPOS,YPOS PRESENT POSITION ; DX,DY SIZE OF LINE SEGMENT ALONG X,Y AXIS ; EPSLNX,EPSLNY,SX,SY,DELTA3 LOCAL VARIABLES ; REGISTER STATUS: ; ALL REGISTER VALUES DESTROYED. ; ERROR CONDITIONS: ; NONE PECULIAR TO THIS ROUTINE ; COMPSEG LHLD NI ;GET COUNTER VALUE INX H ;NI JNZ DOPT ;DX > D3- PLOT POINT MOV A,L ;HIGH BYTES =: LOOK @ LOW BYTES CMP E ;NOW LOW BYTES JNC DOPT ;D3<=DX: PLOT POINT CONT2 MOV A,E ;COMPUTE D3=D3-DX SUB L ;SUBTRACT LOW BYTE FIRST MOV L,A ;PUT LOW BYTE IN POSITION FOR STORE MOV A,D ;NOW HIGH BYTE OF D3 SBB H ;SUBTRACT HIGH BYTE MOV H,A ;PUT HI BYTE IN POSITION FOR STORE SHLD DELTA3 ;STORE RESULT LHLD SX ;COMPUTE XPOS=XPOS+SX XCHG ;PUT SX IN (DE) LHLD XPOS ;FETCH X POSITION DAD D ;ADD SX TO XPOS SHLD XPOS ;STORE RESULT LHLD SY ;COMPUTE YPOS=YPOS+SY XCHG ;PUT SY IN (DE) LHLD YPOS ;FETCH Y POSITION DAD D ;ADD SY SHLD YPOS ;STORE NEW Y POSITION DOPT RET ;RETURN SO CALLING SUB CAN USE POSITION. ; ;----------------------------------------------------------------------- ; CARRIAGE RETURN ROUTINE ; ; INPUTS: ; NONE ; ; OUTPUTS: ; PRINTER CARRIAGE IS RETURNED AND PAPER ADVANCED ; ; REGISTER STATUS: ; ALL VALUES PRESERVED ; ; ERROR CONDITIONS: ; NONE ; CRLF PUSH PSW ;SAVE ALL REGISTERS PUSH B PUSH D PUSH H ; MVI C,05H ;SELECT LIST OUTPUT MVI E,0DH ;PASS CARRIAGE RETURN CHARACTER CALL PDOS MVI C,05H ;SELECT LIST OUTPUT MVI E,0AH ;PASS LINE FEED CHARACTER CALL PDOS ;SEND IT OUT POP H ;RESTORE REGISTERS POP D POP B POP PSW RET ; ;----------------------------------------------------------------------- ; THIS SUBROUTINE FORMS THE MASK FOR THE PLOTTING OF A POINT ; DIGIT= YCOORD MOD 7 ; INPUTS: ; XCOORD IN BC ; YCOORD IN DE ; XYADDR IN HL ; OUTPUTS: ; CONTENTS OF XYADDR IN B ; MASK (1 BIT ON) IN C ; YCOORD IN DE ; XYADDR IN HL ; REGISTER STATUS: ; SEE OUTPUTS ; ERROR CONDITIONS: ; OVERFLOW IN DIVIDE CALLS WOOPS ; DIGIT PUSH H ;SAVE XYADDRESS PUSH D ;SAVE YCOORD CALL CLRMSK ;PREPARE COLOR MASK FOR FUTURE USE XCHG ;PUT YCOORD IN HL SHLD DIVDND ;CALCULATE YCOORD MOD 7 MVI A,07H STA DIVSOR CALL DIVIDE ;MOD IS DIVIDE W/O QUOTIENT LDA RMANDR ;GET RESULT ORA A ;SET FLAGS CM WOOPS ;RMANDR= -1 ON OVERFLOW MOV B,A ;MOVE # OF DIGIT TO B MVI A,00H INR B ;INCREMENT B TO INIT FOR 1ST DEC IF MSBTOP STC ;CLEAR ACCUM, PUT 1 IN CARRY ROTMASK RAL ;MOVE MASK BIT 1 LEFT ENDIF ;(MSBTOP) ; IF NOT MSBTOP MVI A,10000000B ;SET HIGH BIT AND ROTATE IT RIGHT ROTMASK RRC ;MOVE MASK BIT 1 RIGHT ENDIF ;(NOT MSBTOP) ; DCR B ;DECREMENT # OF DIGIT JNZ ROTMASK ;LOOP BACK MOV C,A ;STORE MASK TEMPORARILY LDA CMASK ;GET COLOR MASK ANA C ;AND BIT MASK WITH COLOR MASK- BOTH RQD MOV C,A ;PUT MASK IN C POP D ;BRING BACK YCOORD POP H ;BRING BACK (XYADDR) MOV B,M ;GET BYTE @ (XYADDR) RET ; ;----------------------------------------------------------------------- ; DIVISION SUBROUTINE ; INPUTS: ; DIVDND TWO BYTE POSITIVE NUMBER ; DIVSOR ONE BYTE POSITIVE NUMBER ; OUTPUTS: ; QOTENT ONE BYTE POSITIVE QUOTIENT ; RMANDR ONE BYTE POSITIVE REMAINDER OR FLAG ; REGISTER STATUS: ; BC,DE,HL,PSW REGISTERS RETURNED TO ORIGINAL VALUES ; ERROR CONDITIONS: ; RMANDR=-1 IF OVERFLOW OCCURS ; DIVIDE PUSH PSW ;SAVE REGISTERS PUSH B PUSH D PUSH H LHLD DIVDND ;FETCH DIVIDEND XCHG ;PUT DIVIDEND INTO THE DE PAIR LDA DIVSOR ;FETCH DIVSOR MOV C,A ;SAVE IN REGISTER C MVI B,8 ;LOOP COUNTER IN REGISTER B DIVLOOP MOV A,E ;SHIFT LOW ORDER BYTE TO LEFT ANA A ;CLEAR CARRY RAL ;SHIFT MOV E,A ;REPLACE VALUE MOV A,D ;FETCH HIGH ORDER BYTE RAL ;ROTATE BRINGING IN HIGH BIT SUB C ;SUBTRACT DIVISOR JP SETBIT ;IF RESULT WAS POSITIVE, JUMP ADD C ;OTHERWISE ADD BACK DIVISOR MOV D,A ;REPLACE HIGH ORDER BYTE JMP NEXT ;GO TO INCREMENT PHASE SETBIT MOV D,A ;REPLACE HIGH ORDER BYTE MOV A,E ;FETCH LOW ORDER BYTE ORI 1 ;SET LOW ORDER BIT MOV E,A ;REPLACE LOW ORDER BYTE NEXT DCR B ;DECREMENT LOOP COUNTER JNZ DIVLOOP ;REPEAT UNTIL DONE MOV A,E ;QUOTIENT ANA A ;TEST SIGN OF RESULT JP OK ;IF POSITIVE RESULT IS ACCURATE MVI A,0FFH ;SET OVERFLOW VALUE STA RMANDR JMP DONE OK STA QOTENT ;SAVE QUOTIENT MOV A,D ;REMAINDER STA RMANDR ;SAVE REMAINDER DONE POP H POP D POP B POP PSW RET ; ;----------------------------------------------------------------------- ; ; THIS SUBROUTINE PLOTS THE VERTICAL LINE USED TO FILL IN AREAS ; ; INPUTS: ; XPOS,YPOS CURRENT POSITION ON SEGMENT ; YFILL HORIZONTAL LEVEL TO FILL TO ; OUTPUTS: ; VERTICAL LINE FROM (XPOS,YPOS) TO (XPOS,YFILL) ; REGISTER STATUS: ; ALL REGISTER VALUES DESTROYED ; ERROR CONDITIONS: ; NONE PECULIAR TO THIS ROUTINE. ; NOTE: ALL COORDINATE VALUES ASSUMED TO BE POSITIVE ; FILINE CALL STAT ;UPDATE STATUS MESSAGE LHLD XPOS ;GET STARTING COORDINATES OF LINE SHLD XDOT ;XPOS WILL BE X COORD OF ALL DOTS LHLD YPOS ;GET Y COORDINATE PUSH H ;SAVE Y POSITION- PLOTDOT WILL RESET IT XCHG ;PUT Y COORDINATE IN [DE] LHLD YFILL ;GET Y FILL VALUE ; MOV A,D ;COMPARE Y COORDINATES FOR TOP AND BOT. CMP H ;COMPARE HIGH BYTES JC YFXCH ;CARRY INDICATES THAT YFILL IS > YPOS JNZ CONTFIL ;YFILL DEFINITELY LESS THAN YPOS MOV A,E ;HIGH BYTES EQUAL- COMPARE LOW BYTES CMP L ;IS YFILL ABOVE OR BELOW YPOS? JNC CONTFIL ;YFILL IS NOT ABOVE YPOS- CONTINUE YFXCH XCHG ;SWITCH YPOS AND YFILL- LARGER VAL IN DE CONTFIL SHLD YDOT ;PASS Y COORDINATE TO PLOTDOT PUSH D ;SAVE REGISTERS PUSH H CALL PLOTDOT ;PLOT POINT POP H ;RETRIEVE REGISTERS POP D INX H ;INCREMENT Y POSITION ; MOV A,D ;CHECK TO SEE IF LINE IS DONE CMP H ;COMPARE HIGH BYTES JC DONEFIL ;CARRY INDICATES THAT NEW Y IS ABOVE END JNZ CONTFIL ;NEW COORDINATE DEFINITELY BELOW END MOV A,E ;HIGH BYTES EQUAL- COMPARE LOW BYTES CMP L ;IS IT THERE YET? JC DONEFIL ;CARRY INDICATES THAT NEW Y IS ABOVE END JMP CONTFIL ;LOOP BACK AND DO NEXT POINT DONEFIL POP H ;RETRIEVE LINE Y POSITION SHLD YPOS ;RESTORE VALUE RET ;ALL FINISHED! ; ;----------------------------------------------------------------------- ; ; THIS SUBROUTINE WILL FILL AN AREA BETWEEN A LINE SEGMENT AND ; A HORIZONTAL LINE ; ; INPUTS: ; BUFFER CONTAINING COORDINATE PAIRS AND Y COORDINATE OF ; FILL LEVEL. ALL FIVE ARE REAL VALUES ; OUTPUTS: ; XPOS,YPOS UPDATED TO END OF LINE SEGMENT ; AREA BETWEEN SEGMENT AND YFILL IS FILLED WITH CURRENT ; COLOR VALUE ; REGISTER STATUS: ; ALL REGISTERS DESTROYED ; ERROR CONDITIONS: ; NONE PECULIAR TO THIS ROUTINE ; FILL CALL READXY ;GET STARTING COORDINATES LHLD X SHLD XPOS ;UPDATE X POSITION TO START OF SEGMENT LHLD Y SHLD YPOS ;UPDATE Y POSITION TO START OF SEGMENT CALL READXY ;GET END COORDINATES CALL BYTE ;GET FIRST BYTE OF FIXED PT. Y FILL PUSH PSW ;STORE FIRST BYTE CALL BYTE ;GET SECOND BYTE MOV B,A ;PUT HIGH BYTE IN [B] POP PSW ;GET LOW BYTE MOV C,A ;[BC] NOW CONTAINS FIXED POINT Y COORD. LXI D,MAXY*2 ;PASS MAXIMUM RASTER ADDRESS CALL MULT ;MULTIPLY Y COORD BY NO. OF Y RASTERS XCHG ;PUT HIGH BYTES IN [HL] SHLD YFILL ;SAVE INTEGER VALUE OF Y FILL LEVEL ; CALL SEGINIT ;INITIALIZE VARIABLES FOR SEG. INTERP. CALL FILINE ;FILL AREA BETWEEN FIRST PT. & YFILL STRTFIL CALL COMPSEG ;COMPUTE NEXT POINT IN SEGMENT LHLD DELTAX ;TOP OF LOOP- END WHEN NI>DX XCHG ;DELTAX IS NOW IN (DE) LHLD NI ;GET COUNTER MOV A,D ;COMPARE COUNTER W/DX HI BYTE FIRST CMP H ;COMPARE HI BYTES RC ;CARRY INDICATES NI HI BYTE>DX HI BYTE JNZ CHKFIL ;CONTINUE IF NI DEFINITELY < DX MOV A,E ;HIGH BYTES EQUAL- LOOK @ LOW BYTE CMP L ;NOW LOW BYTE RC ;NI LOW BYTE>DX LOW BYTE- DONE W/SEGMENT CHKFIL LHLD XDOT ;COMPARE XDOT AND XPOS XCHG LHLD XPOS ;XPOS=XDOT=> THIS WILL DUPLICATE FILL MOV A,D CMP H ;ARE HIGH BYTES THE SAME? JNZ LOOPFIL ;GO ON IF HIGH BYTES ARE NOT EQUAL MOV A,E ;HIGH BYTES EQUAL- LOOK AT LOW BYTES CMP L ;ARE THE TWO EXACTLY THE SAME? JZ STRTFIL ;YES- SKIP THIS POSITION LOOPFIL CALL FILINE ;FILL AREA BETWEEN SEGMENT & YFILL JMP STRTFIL ;LOOP BACK TO TOP ; ;----------------------------------------------------------------------- ; ; THIS SUBROUTINE WILL SEND A STRING OF CHARACTERS TO THE PRINTER ; ; INPUTS: ; NUMBER-1 OF CHARACTERS TO SEND IN [DE] ; ADDRESS-1 OF FIRST CHARACTER IN [HL] ; OUTPUTS: ; 0 THROUGH [DE] CHARACTERS SENT TO PRINTER ; REGISTER STATUS: ; ALL REGISTERS DESTROYED ; ERROR CONDITIONS: ; NONE DETECTED BY THIS ROUTINE ; GBOLOOP NOP IF OKI PUSH D PUSH H MVI C,05H ;SEND ETX TO START INTO GRAPHIC MODE MVI E,03H CALL PDOS POP H POP D ENDIF ;(OKI) ; KIRKLOP DCX D ;DECREMENT COUNTER INX H ;INCREMENT ADDRESS PUSH D ;SAVE COUNTER PUSH H MOV E,M ;GET CHARACTER ; IF OKI ;IF GRAPHIC BYTE IS , A SECOND ; IS REQUIRED FOR THE OKI PRINTER MOV A,E CPI 03H ;IS BYTE ? JNZ GBOLP1 PUSH D ;SAVE BYTE MVI C,05H ;SELECT CP/M LIST FUNCTION CALL PDOS MVI E,03H ;REPLACE CHARACTER SENT POP D ;SAVE BYTE ENDIF ;(OKI) ; GBOLP1 MVI C,05 ;SELECT CP/M LIST OUTPUT FUNCTION CALL PDOS ;SEND CHARACTER OUT POP H ;RETRIEVE ADDRESS POP D ;RETRIEVE COUNTER MOV A,E ;IS COUNTER =0? ORA D ;TEST COUNTER JNZ KIRKLOP ;NOT DONE: LOOP BACK IF OKI ;SEND ETX-SO TO CANCEL GRAPHICS MODE PUSH D ;SAVE COUNTER PUSH H ;SAVE ADDRESS MVI C,05H MVI E,03H CALL PDOS MVI C,05H MVI E,02H CALL PDOS POP H ;RETRIEVE ADDRESS POP D ;RETRIEVE COUNTER ENDIF ;(OKI) ; RET ; ;----------------------------------------------------------------------- ; THIS ROUTINE SAVES A BYTE FROM BIT MAP IN GRAPHIC BUFFER ; ; INPUTS: ; BYTE IN (B) ; 2 BYTE COUNTER @ NGRAPH ; ; OUTPUTS: ; NGRAPH INCREMENTED ; BYTE STORED IN BUFFER @ GBUFF ; BUFFER FLUSHED IF FULL ; ; REGISTER STATUS: ; ALL REGISTERS PRESERVED ; ; ERROR CONDITIONS: ; NONE ; GBUFIN PUSH PSW ;SAVE REGISTERS PUSH B PUSH D PUSH H ; LHLD NGRAPH ;GET NO. OF BYTES IN BUFFER INX H ;INCREMENT NGRAPH SHLD NGRAPH ;STORE NEW VALUE XCHG ;PUT NGRAPH IN [DE] ; LXI H,GBUFF-1 ;GET BUFFER BASE ADDRESS DAD D ;ADD COUNTER TO BASE ADDRESS MOV M,B ;STORE BYTE ; ; XCHG ;PUT NGRAPH IN [HL] LXI D,0-(MAXX+1) ;PUT -MAX NO. OF BYTES IN [DE] DAD D ;[HL]=NGRAPH-(MAX NO. OF BYTES) MOV A,H ;IF [HL]=0 THEN BUFFER IS FULL ORA L ;SET FLAGS CZ GBUFOUT ;BUFFER IS FULL- FLUSH IT TO PRINTER ; POP H ;RESTORE REGISTERS POP D POP B POP PSW RET ; ;----------------------------------------------------------------------- ; THIS SUBROUTINE FLUSHES THE GRAPHIC BUFFER ; ; INPUTS: ; GRAPHIC BUFFER @ GBUFF ; NUMBER OF VALID BYTES IN BUFFER @ NGRAPH ; "ESC K" SEQUENCE STORED AHEAD OF NGRAPH ; ; OUTPUTS: ; PRINTER IS PLACED IN DOT GRAPHIC MODE ; GRAPHIC STRING TRANSMITTED BYTE BY BYTE TO PRINTER ; ; REGISTER STATUS: ; ALL REGISTERS PRESERVED ; ; ERROR CONDITIONS: ; NONE ; GBUFOUT PUSH PSW ;SAVE REGISTERS PUSH B PUSH D PUSH H ; GBOTOP LHLD NGRAPH ;FETCH BUFFER COUNTER XCHG ;PUT BUFFER COUNTER IN [DE] MOV A,E ;LOOK AT LOW BYTE ORA D ;IS COUNTER=0? JZ GBUFRET ;IF BUFFER IS EMPTY, DON'T O/P ANYTHING ; ; SKIP TOTALLY BLANK LINES ; LXI B,MAXX+1 ;GET LENGTH OF BUFFER MOV A,B ;COMPARE HIGH BYTES FIRST CMP D JNZ GBO2 ;NO MATCH INDICATES SOMETHING ON THIS LINE MOV A,C ;COMPARE LOW BYTES NEXT CMP E JNZ GBO2 ;NO MATCH INDICATES SOMETHING ON THIS LINE ; LXI H,GBUFF ;SET POINTER TO START OF BUFFER GBO1 MOV A,M ;GET BYTE FROM BUFFER ORA A ;IS IT A BLANK STROKE? JNZ GBO2 ;GO TO OUTPUT SECTION IF NOT BLANK INX H ;POINT TO NEW BYTE DCX B ;DECREMENT COUNTER MOV A,B ;CHECK FOR ZERO ORA C JNZ GBO1 ;REPEAT UNTIL LAST BYTE HAS BEEN CHECKED ; JMP GBUFRET ;RETURN W/O PLOTTING SINCE ALL WERE BLANK ; GBO2 NOP ;HEAD OF OUTPUT SECTION ; IF NO8BIT MOV A,E ;LOOK AT LOW BYTE OF COUNTER ORA A ;SET FLAGS- IS HIGH BIT SET? JP GBO7 ;LOW BYTE HAS 7 BITS-O/P WHOLE THING. ; ; THE PARALLEL INTERFACE WILL ONLY TRANSMIT 7 BITS. THE LOW BYTE ; OF THE BUFFER COUNTER HAS ITS HIGH BIT SET, THEREFORE, THE ; BUFFER MUST BE OUTPUT IN SMALLER CHUNKS ; PUSH D ;SAVE NGRAPH ON STACK ENDIF ;(NO8BIT) IF EPSON AND NO8BIT LXI D,126+4 ;COUNTER=>126 BYTES + 4 FOR ESCK,NGRAPH LXI H,126D ;SET NGRAPH TO 126 SHLD NGRAPH ;PUT NEW NO. IN PRINTER SEQUENCE LXI H,ESCK-1 ;START WITH ESCAPE SEQUENCE ENDIF ;(EPSON AND NO8BIT) ; IF CITOH AND NO8BIT LXI D,126+6 ;COUNTER=>126 BYTES + 6 FOR ESC S N3210 LXI H,ESCK+3 ;ADDRESS OF N1 BYTE LXI B,126D ;SET NO. OF BYTES MOV M,B ;STORE HIGH BYTE IN N1 INX H ;ADDRESS OF N0 MOV M,C ;STORE LOW BYTE IN N0 LXI H,ESCK-1 ;START WITH ESCAPE SEQUENCE ENDIF ;(CITOH AND NO8BIT) ; IF NO8BIT CALL GBOLOOP ;SEND OUT FIRST 126 CHARACTERS ; ; MOVE CHARACTERS IN BUFFER UP TO REPLACE THOSE SENT OUT ; POP H ;RETRIEVE OLD VALUE OF NGRAPH LXI D,0FF82H ;[DE]=-126D DAD D ;[HL]NOW=NGRAPH-126 SHLD NGRAPH ;STORE NEW VALUE XCHG ;PUT NGRAPH IN [DE] TO ACT AS COUNTER LXI H,GBUFF-1 ;GET BASE ADDRESS OF BUFFER PUSH H ;SAVE POINTER FOR SAVING DATA LXI B,007EH ;PUT 126D IN [BC] DAD B ;[HL] NOW POINTS TO NEW BYTES ; GBOMOV INX H ;INCRMENT NEW DATA POINTER MOV A,M ;GET BYTE FROM BUFFER XTHL ;EXCHANGE POINTERS INX H ;INCREMENT SAVE DATA POINTER MOV M,A ;MOVE BYTE UP IN BUFFER XTHL ;EXCHANGE POINTERS BACK AGAIN DCX D ;DECREMENT COUNTER MOV A,E ;CHECK TO SEE IF LOOP IS DONE ORA D ;IS [DE]=0? JNZ GBOMOV ;LOOP BACK UP IF NOT DONE POP H ;RETRIEVE POINTER TO CLEAN UP STACK ; ; NGRAPH HAS NOW BEEN UPDATED AND DATA IN BUFFER HAS BEEN MOVED ; TO REPLACE THAT WHICH HAS BEEN SENT OUT. NOW READY TO TRY ALL ; OVER AGAIN WITH NEW SEGMENT OF DATA IN BUFFER. ; JMP GBOTOP ENDIF ;(NO8BIT) ; IF EPSON GBO7 INX D INX D INX D INX D LXI H,ESCK-1 ;START WITH ESCAPE SEQUENCE ENDIF ;(EPSON) ; IF CITOH GBO7 LXI H,ESCK+2 ;ADDRESS OF N3 BYTE FOR GRAPHICS SELECT MVI A,30H ;INITIALIZE NUMBER OF BYES TO "0000" MOV M,A ;"0" INX H MOV M,A ;"00" INX H MOV M,A ;"000" INX H MOV M,A ;"0000" ; CALL BINDEC ;CONVERT N TO ASCII DECIMAL AND STORE ; INX D ;INCREMENT COUNTER FOR ESC S N3-N0 INX D INX D INX D INX D INX D LXI H,ESCK-1 ;START WITH ESCAPE SEQUENCE ENDIF ;(CITOH) ; IF OKI GBO7 LXI H,GBUFF-1 ENDIF ;(OKI) ; CALL GBOLOOP ;SEND OUT STRING OF GRAPHIC CHARACTERS ; GBUFRET MVI A,00H ;CLEAR ACCUMULATOR STA NGRAPH ;SET NGRAPH=0 STA NGRAPH+1 POP H ;RESTORE REGISTERS POP D POP B POP PSW RET ; ;----------------------------------------------------------------------- ; THIS SUBROUTINE PLOTS AN INCREMENTAL LINE SEGMENT FROM THE ; PRESENT POSITION ; INPUTS: ; FILE BUFFER @ DMA ; PRESENT POSITION @ XPOS,YPOS ; OUTPUTS: ; XPOS, YPOS UPDATED TO X,Y ; VISIBLE PORTION OF LINE SEGMENT DRAWN ; REGISTER STATUS: ; ALL REGISTER VALUES DESTROYED ; ERROR CONDITIONS: ; NONE PECULIAR TO THIS ROUTINE ; INCPLT CALL READXY ;GET END POINT VALUES CALL SEGINIT ;INITIALIZE SEGMENT INTERPOLATION SUB. ; STRTPLT LHLD DELTAX ;TOP OF LOOP- END WHEN NI>DX XCHG ;DELTAX IS NOW IN (DE) LHLD NI ;GET COUNTER MOV A,D ;COMPARE COUNTER W/DX HI BYTE FIRST CMP H ;COMPARE HI BYTES RC ;CARRY INDICATES NI HI BYTE>DX HI BYTE JNZ CONTPLT ;CONTINUE IF NI DEFINITELY < DX MOV A,E ;HIGH BYTES EQUAL- LOOK @ LOW BYTE CMP L ;NOW LOW BYTE RC ;NI LOW BYTE>DX LOW BYTE- DONE W/SEGMENT CONTPLT CALL COMPSEG ;COMPUTE XPOS AND YPOS AT NEXT POINT LHLD XPOS ;FETCH X POSITION SHLD XDOT ;PASS IN XDOT LHLD YPOS ;FETCH Y POSITION SHLD YDOT ;PASS IN YDOT CALL PLOTDOT ;PLOT IT (FINALLY) JMP STRTPLT ;BOUNCE UP TO THE TOP OF THE LOOP ; ;----------------------------------------------------------------------- ; LINE SPACING SUBROUTINE ; ; INPUTS: ; NONE ; OUTPUTS: ; FORM FEED SENT ; ESC A 7 SENT TO SET THE PRINTER TO 7/72" LINE SPACING ; REGISTER STATUS: ; ALL VALUES CHANGED ; ERROR CONDITIONS: ; NONE ; IF EPSON LN772 MVI C,05H ;SELECT LIST OUTPUT ; MVI E,0CH ;PASS FORMFEED ; CALL PDOS ;SEND IT OUT ; ; MVI C,05H ;SELECT LIST OUTPUT MVI E,1BH ;PASS ESC CHARACTER CALL PDOS ;SEND IT OUT ; MVI C,05H ;SELECT LIST OUTPUT MVI E,'A' ;PASS "A" CALL PDOS ;SEND IT OUT ; MVI C,05H ;SELECT LIST OUTPUT MVI E,07H ;PASS 7 FOR 7/72" CALL PDOS ; RET ENDIF ;(EPSON) ; IF CITOH LN772 MVI C,05H ;SELECT LIST OUTPUT ; MVI E,0CH ;PASS FORMFEED ; CALL PDOS ;SEND IT OUT ; ; MVI C,05H ;SELECT LIST OUTPUT MVI E,1BH ;PASS ESC CHARACTER CALL PDOS ;SEND IT OUT ; MVI C,05H ;SELECT LIST OUTPUT MVI E,'>' ;ESC > SETS UNIDIRECTIONAL PRINTING CALL PDOS ;SEND IT OUT ; MVI C,05H ;SELECT LIST OUTPUT MVI E,1BH ;PASS ESC CHARACTER CALL PDOS ;SEND IT OUT ; MVI C,05H ;SELECT LIST OUTPUT MVI E,'T' ;PASS "T" CALL PDOS ;SEND IT OUT ; MVI C,05H MVI E,'1' CALL PDOS ;SEND OUT 1 AS HIGH BYTE ; MVI C,05H ;SELECT LIST OUTPUT MVI E,'4' ;PASS 14 FOR 14/144" CALL PDOS ; RET ENDIF ;(CITOH) ; IF OKI LN772 MVI C,05H MVI E,18H ;CLEAR PRINTER CALL PDOS MVI C,05H MVI E,1CH ;SET 12 CPI CALL PDOS MVI C,05H MVI E,1BH ;ESC % "9" 14 TO SET LINE SPACING CALL PDOS MVI C,05H MVI E,25H CALL PDOS MVI C,05H MVI E,39H CALL PDOS MVI C,05H MVI E,14D ;14/144 "/LINE CALL PDOS RET ENDIF ;(OKI) ; ;----------------------------------------------------------------------- ; THIS SUBROUTINE CALCULATES THE ADDRESS FOR AN XY COORDINATE PAIR ; XYADDR= ORIGIN + XCOORD + (MAXY-YCOORD)/7 * (MAXX+1) ; INPUTS: ; XCOORDINATE IN REGISTERS BC ; YCOORDINATE IN REGISTERS DE ; MAXIMUM Y RASTER COUNT IN HL ; OUTPUTS: ; XCOORDINATE IN REGISTERS BC ; YCOORDINATE IN REGISTERS DE ; ADDRESS OF X,Y COORDINATES IN HL ; ADDRESS STORED @ XYADDR ; REGISTER STATUS: ; PSW VALUES CHANGED ; ERROR CONDITIONS: ; OVERFLOW OF ARITHMETIC CALLS WOOPS ; LOCDOT PUSH D ;STORE Y COORD ON STACK PUSH B ;STORE X COORD ON STACK MOV A,L SUB E ;SUBTRACT YCOORD FROM MAXY MOV L,A MOV A,H SBB D MOV H,A ;[HL] NOW CONTAINS (MAXY - Y) SHLD DIVDND ;PASS (MAXY - Y) TO DIVISION ROUTINE MVI A,07H ;PASS 7 TO DIVISION ROUTINE STA DIVSOR CALL DIVIDE ;(MAXY - Y)/7 LDA RMANDR ;RMANDR IS NEGATIVE IF OVERFLOW ORA A ;SET FLAGS CM WOOPS ;OVERFLOW IN DIVISION LDA QOTENT ;GET RESULT OF DIVISION LXI B,MAXX+1 ;[BC] NOW CONTAINS THE MAX. NO. OF X'S CALL BMULT ;[HL] HAS LOW ORDER BYTES, [A] THE HIGH ; [HL] NOW CONTAINS (MAX-YCOORD)/7*(MAX+1) POP B ;PUT XCOORD IN [BC] DAD B ;ADD TO X PREVIOUS TERM LXI D,ORIGIN ;LAST TERM DAD D ;FINAL SUM IS IN [HL] SHLD XYADDR ;STORE RESULT POP D ;RETRIEVE Y COORDINATE RET ; ;----------------------------------------------------------------------- ; OUTPUT ROUTINE ; ; INPUTS: ; MEMORY MAP STARTING @ ORIGIN ; ; OUTPUTS: ; MAP IS DUMPED TO PRINTER 1 BYTE AT A TIME ; MIXED GRAPHICS AND TEXT ARE OUTPUT ; ; REGISTER STATUS: ; ALL VALUES DESTROYED ; ; ERROR CONDITIONS: ; NONE. PRINTER WILL HANG IF IT DOESN'T GET PROPER INPUT ; MAPOUT MVI A,00H ;RESET STATUS COUNTER STA STATNO MVI C,09H ;PRINT PRINTING STATUS MESSAGE LXI D,STAT3 CALL FDOS ; CALL LN772 ;SET PRINTER TO 7/72" LINE SPACING LXI H,ORIGIN ;INITIAIZE START ADDRESS MVI A,00H ;CLEAR ACCUMULATOR STA NGRAPH ;INITIALIZE GRAPHICS COUNTER STA NGRAPH+1 MVI C,(MAXY+1)/7 ;INITIALIZE LINE COUNTER LINLOOP LXI D,MAXX+1 ;INITIALIZE DOT COUNTER ; BYTLOOP MOV B,M ;GET BYTE MOV A,B ;PUT BYTE IN (A) ORA A ;SET FLAGS - IS IT A GRAPHIC BYTE? CM CHAROUT ;NO- HI BIT SET THEREFORE CHARACTER CP GBUFIN ;YES- SAVE IT IN GRAPHIC BUFFER ; INX H ;INCREMENT ADDRESS TO NEXT X LOCATION DCX D ;DECREMENT DOT COUNTER MOV A,D ORA E ;IS DOT COUNTER = 0? JNZ BYTLOOP ;NO- SO LOOP TO TOP AGAIN ; CALL GBUFOUT ;AT END OF LINE- FLUSH BUFFER CALL CRLF ;SEND A LINE FEED TO PRINTER DCR C ;DECREMENT LINE COUNTER MOV A,C ;GET READY TO TEST LINE COUNTER ORA A ;SET FLAGS ON LINE COUNTER JNZ LINLOOP ;NOT DONE- REPEAT OUTER LOOP ; CALL PRESET ;RESET PRINTER TO NORMAL MODE ; RET ;LAST LINE FINISHED ; ;----------------------------------------------------------------------- ; THIS SUBROUTINE MOVES THE PRESENT POSITION TO NEW COORDINATES ; WITHOUT DOING ANYTHING ELSE ; ; INPUTS: ; COORDINATE PAIR IN BUFFER ; OUTPUTS: ; XPOS AND YPOS UPDATED TO NEW COORDINATES ; REGISTER STATUS: ; ALL VALUES DESTROYED ; ERROR CONDITIONS: ; NONE PECULIAR TO THIS ROUTINE ; MOVE CALL READXY ;GET COORDINATE PAIR LHLD X ;GET X COORDINATE SHLD XPOS ;UPDATE X AXIS POSITION LHLD Y ;GET Y COORDINATE SHLD YPOS ;UPDATE Y AXIS POSITION RET ;POSITION NOW UPDATED. ; ;----------------------------------------------------------------------- ; ; THIS SUBROUTINE MULTIPLIES TWO 16 BIT INTEGERS ; ; THIS ROUTINE FROM ELECTRONICS MAGAZINE, FEB. 24, 1982. ; WRITTEN BY JERRY L. GOODRICH, PENN. STATE U. ; ; ; INPUTS: ; MULTIPLICAND IN [BC] ; MULTIPLIER IN [DE] ; OUTPUTS: ; 32 BIT PRODUCT IN [DE],[HL] (MOST SIG. BITS IN [DE]) ; REGISTER STATUS: ; SEE INPUTS AND OUTPUTS ; ERROR CONDITIONS: ; NONE ; MULT MOV A,E ;LOAD LOWEST ORDER BYTE OF MULTIPLIER PUSH D ;SAVE HIGHEST ORDER BYTE OF MULTIPLIER CALL BMULT ;DO 1-BYTE MULTIPLY XTHL ;SAVE LOWEST ORDER BYTES PRODUCT, GET MULTIPLIER PUSH PSW ;STORE HIGHEST ORDER BYTE OF FIRST PROD. MOV A,H ;LOAD HIGHEST ORDER BYTE OF MULTIPLIER CALL BMULT ;DO SECOND 1-BYTE MULTIPLY MOV D,A ;POSITION HIGHEST-ORDER BYTE OF PRODUCT POP PSW ;GET HIGHEST ORDER BYTE OF FIRST PRODUCT ADD H ;UPDATE THIRD BYTE OF PRODUCT MOV E,A ;AND PUT IT IN E JNC NC1 ;DONT'T INCREMENT D IF NO CARRY INR D ;INCREMENT D IF CARRY NC1: MOV H,L ;RELOCATE LOWEST ORDER BYTES OF 2ND PROD MVI L,0 POP B ;GET LOWEST ORDER 2 BYTES OF FIRST PROD. DAD B ;GET FINAL PRODUCT LOWEST ORDER 2 BYTES RNC ;DONE IF NO CARRY INX D ;OTHERWISE UPDATE HIGHEST ORDER 2 BYTES RET ; ;----------------------------------------------------------------------- ; PRINT OR DISK O/P SUBROUTINE ; ; INPUTS: ; 05H IN (C) ; CHARACTER IN (E) ; BUFFER POINTER SET TO LAST CHARACTER (POINTR2) ; O/P FLAG IN OPDISK ; OUTPUTS: ; CHARACTER PRINTED IF O/P FLAG SET ; CHARACTER WRITTEN TO DISK IF FLAG IS SET ; REGISTER STATUS: ; ALL REGISTER VALUES DESTROYED ; ERROR CONDITIONS: ; NONE IN THIS ROUTINE. ; PDOS LDA OPDISK ;GET DISK O/P FLAG CPI 00H ;IS FLAG SET? PUSH PSW ;SAVE FLAG CZ FDOS ;PRINT CHARACTER IF IT IS POP PSW ;RETRIEVE FLAGS RZ ;RETURN IF CHARACTER WAS PRINTED ; LDA POINTR2 ;GET BUFFER POINTER INR A ;INCREMENT POINTER FOR NEW CHAR. STA POINTR2 ;SAVE NEW VALUE MOV C,A ;SAVE POINTER VALUE IN (C) MVI B,0 ;CLEAR HIGH BYTE OF (BC) LXI H,DMA2-1 ;GET LAST ADDR. BEFORE DMA2 DAD B ;CALCULATE ADDRESS OF BYTE MOV M,E ;PUT CHARACTER IN BUFFER CPI 128D ;IS BUFFER FULL? CZ WRITE ;WRITE IT OUT IF IT IS. RET ;DONE ; ;----------------------------------------------------------------------- ; THIS SUBROUTINE PLOTS A POINT @ XDOT,YDOT ; METHOD: ; FIND BYTE CONTAINING XDOT,YDOT ; FORM MASK EG: IF XDOT,YDOT IS IN #4 BIT, ; MASK = 00010000 ; DIGIT= 76543210 ; MODIFY BYTE ACCORDING TO COLOR & STORE IT BACK ; INPUTS: ; 2 BYTE X LOCATION STORED @ XDOT ; 2 BYTE Y LOCATION STORED @ YDOT ; OUTPUTS: ; XPOS, YPOS RESET TO VALUES GIVEN IN XDOT, YDOT ; APPROPRIATE DOT TURNED ON OR OFF IN MEMORY MAP ; REGISTER STATUS: ; ALL REGISTER VALUES DESTROYED ; ERROR CONDITIONS: ; IF XDOT OR YDOT ARE OUTSIDE OF WINDOW, NO POINT PLOTTED ; XPOS AND YPOS WILL STILL POINT OUTSIDE WINDOW ; PLOTDOT LHLD XDOT ;GET X POSITION SHLD XPOS ;UPDATE CURRENT POSITION MOV B,H ;MOVING XDOT TO BC MOV C,L ;XDOT NOW IN BC LHLD YDOT ;GET Y POSITION SHLD YPOS ;UPDATE CURRENT POSITION MOV D,H ;MOVING YDOT TO DE MOV E,L ;YDOT NOW IN DE ;XPOS AND YPOS NOW CONTAIN LAST POS. ATTEMPTED- MAY NOT BE IN WINDOW LXI H,MAXX ;PUT LIMITS OF X IN HL XCHECK MOV A,B ;CHECK FOR NEG X-SIGN IN HI BYTE ORA A ;IS XDOT NEGATIVE? RM ;XDOT NEG- RETURN W/O PLOTTING MOV A,H ;WORK WITH HIGH BYTE FIRST CMP B ;COMPARE MAX & X HIGH BYTES RC ;X>MAX- THEREFORE RETURN JNZ YCHECK ;X IS OK- CHECK Y MOV A,L ;HIGH BYTES ARE= LOOK @ LOW BYTE CMP C ;COMPARE X & MAX LOW BYTES RC ;X>MAX- RETURN W/O PLOTTING YCHECK LXI H,MAXY ;PUT LIMIT OF Y IN HL MOV A,D ;YDOT HI BYTE CONTAINS SIGN ORA A ;IS YDOT NEGATIVE? RM ;YDOT NEG- RETURN W/O PLOTTING MOV A,H ;HIGH BYTES FIRST CMP D ;COMPARE MAX & Y HIGH BYTES RC ;Y>MAX- RETURN W/O PLOTTING JNZ XYOK ;Y IS OK- PLOT DOT MOV A,L ;HIGH BYTES= LOOK @ LOW BYTES CMP E ;COMPARE LOW BYTES RC ;Y IS > MAX- RETURN W/O PLOTTING XYOK CALL LOCDOT ;GET ADDRESS OF BYTE FOR X,YDOT CALL DIGIT ;FORM MASK FOR PLOTTING MOV A,B ;DETERMINE IF BYTE IS GRAPHIC ORA A ;GRAPHIC? RM ;MINUS= CHARACTER: RETURN W/O PLOTTING LDA COLOR ;GET COLOR VALUE ORA A ;SET FLAGS JZ WHITE ;0 = WHITE JM COMPL ;-1 = COMPLEMENTARY COLOR MOV A,B ;COLOR IS BLACK ORA C ;MODIFY BYTE BY TURNING BIT ON MOV M,A ;STORE BACK IN MEMORY RET ;DONE- ( AT LAST) ; WHITE MOV A,B ;WORK W/ BYTE CONTAINING X,Y CMA ;COMPLEMENT BYTE ORA C ;MODIFY BYTE BY TURNING ON BIT CMA ;COMPLEMENT BYTE BACK- BIT 0FF MOV M,A ;STORE BYTE BACK IN MEMORY RET ;DONE- (FINALY) ; COMPL MOV A,B ;WORK W/ BYTE CONTAINING X,Y XRA C ;COMPLEMENT BIT MOV M,A ;STORE IT RET ;DONE- ; ;----------------------------------------------------------------------- ; PLOT POINT ROUTINE ; ; INPUTS: ; BUFFER @ DMA ; OUTPUTS: ; POINT PLOTTED IN MEMORY ; REGISTER STATUS: ; ALL VALUES CHANGED ; ERROR CONDITIONS: ; NONE ; POINT CALL READXY ;READ COORDINATES FOR POINT LHLD X ;FETCH X LOCATION SHLD XDOT ;PASS X TO DOT ROUTINE LHLD Y ;FETCH Y LOCATION SHLD YDOT ;PSSS Y TO DOT ROUTINE CALL PLOTDOT RET ; ;----------------------------------------------------------------------- ; QUIT ; CLOSES OUTPUT FILE, TERMINATES PROGRAM ; INPUTS: ; FCB FOR OUTPUT FILE @ FCB2 ; DISK OUTPUT FLAG @ OPDISK ; OUTPUTS: ; REMAINDER OF RECORD SET TO 0, DISK CLOSED. ; REGISTER STATUS: ; ALL VALUES DESTROYED ; ERROR CONDITIONS: ; NONE ; QUIT: LDA OPDISK ;GET DISK OUTPUT FLAG CPI 00H ;IS IT SET? JZ BOOT ;NO, SO ALL DONE ; LDA POINTR2 ;LOOK @ O/P POINTER CPI 0 ;IS O/P BUFFER EMPTY? JZ BOOT ;YES- DONE ; ; FILL REMAINDER OF O/P BUFFER WITH NULLS ; MOV E,A ;SAVE POINTER VALUE IN (E) MVI D,00H ;CLEAR HIGH BYTE OF (DE) MVI A,128 ;SET MAX VALUE OF POINTER SUB E ;(A)= 128- POINTR2 MOV C,A ;(C) NOW IS COUNT OF EXTRA BUFF. ; CLRBUF PUSH B ;SAVE COUNTER MVI E,00H ;PASS A CALL PDOS ;PUT IT IN BUFFER POP B ;RETRIEVE COUNTER DCR C ;COUNTER=COUNTER-1 JNZ CLRBUF ;LOOP BACK UNTIL BUFFER IS FULL ; MVI C,10H ;SELECT CLOSE FILE FUNCTION LXI D,FCB2 ;PASS O/P FCB CALL FDOS ;CLOSE FILE ; JMP BOOT ;DO WARM BOOT ON EXIT ; ;----------------------------------------------------------------------- ; LINE SEGMENT ROUTINE ; INPUTS: FILE BUFFER @ DMA ; ; OUTPUTS: ; XPOS, YPOS UPDATED TO X2,Y2 ; VISIBLE PORTION OF LINE SEGMENT PLOTTED ; ; REGISTERS: ; ALL REGISTERS VALUES DESTROYED ; ERROR CONDITIONS: ; NO CHECKS MADE IN THIS ROUTINE ; PLOTSEG CALL READXY ;GET STARTING COORDINATES LHLD X ;FETCH STARTING X SHLD XDOT ;PASS TO DOT ROUTINE LHLD Y ;FETCH STARTING Y SHLD YDOT ;PASS TO DOT ROUTINE CALL PLOTDOT ;PLOT STARTING POINT CALL INCPLT ;PLOT REST OF SEGMENT RET ;RETURN TO MAIN PROGRAM ; ;----------------------------------------------------------------------- ; ; THIS SUBROUTINE RESETS THE PRINTER TO ITS NORMAL MODE ; ; INPUTS: ; NONE ; OUTPUTS: ; NONE RETURNED ; REGISTER STATUS: ; ALL REGISTERS CHANGED ; ERROR CONDITIONS: ; NONE ; IF EPSON PRESET: MVI C,05H MVI E,1BH ;PASS ESC CHARACTER CALL PDOS ;SEND ESC MVI C,05H MVI E,'2' CALL PDOS ;ESC 2 SETS LINE SPACING TO 6 LINES/IN. MVI C,05H MVI E,CR ;SEND CARRIAGE RETURN TO RESET HEAD CALL PDOS RET ENDIF ;(EPSON) ; IF CITOH PRESET: MVI C,05H MVI E,1BH ;SEND ESC CALL PDOS MVI C,05H MVI E,'A' ;ESC A SETS LINE SPACING TO 6 LINES/IN. CALL PDOS MVI E,CR MVI C,05H CALL PDOS ;SEND CARRIAGE RETURN TO RESET HEAD RET ENDIF ;(CITOH) ; IF OKI PRESET: MVI C,05H MVI E,1BH ;ESC % "9" 24 TO SET LINE SPACING CALL PDOS MVI C,05H MVI E,25H ; "%" CALL PDOS MVI C,05H MVI E,39H ; "9" CALL PDOS MVI C,05H MVI E,24D ;RESET TO NORMAL LINE SPACING CALL PDOS RET ; ENDIF ;(OKI) ; ;----------------------------------------------------------------------- ; READ RECORD SUBROUTINE ; INPUTS: ; OPENED FILE ; FILE CONTROL BLOCK @ FCB ; 128 CHAR FILE BUFFER @ DMA ; 1 BYTE CHARACTER POINTER @ POINTER ; OUTPUTS: ; CHARACTER POINTER RESET TO 0 ; NEW RECORD IN FILE BUFFER ; REGISTER STATUS: ; ALL REGISTER VALUES DESTROYED ; ERROR CONDITIONS: ; EOF: JUMP TO EOFEXIT INSTEAD OF NORMAL RETURN ; READ MVI C,26D ;SELECT SET DMA FUNCTION LXI D,DMA ;PASS BUFFER ADDRESS CALL FDOS ;SET DMA ADDRESS TO I/P BUFFER ; MVI C,14H ;SELECT SEQUENTIAL READ FUNCTION LXI D,FCB ;PASS FCB CALL FDOS ;READ RECORD INTO BUFFER @ DMA CPI 00H ;READ OK? JZ SETPNTR ;RESET POINTER IF NOT EOF POP B ;POP RETURN ADDR OFF STACK JMP EOFEXIT ;GOTO EXIT INSTEAD OF NORMAL RTN SETPNTR MVI A,0 ;CLEAR ACCUM. STA POINTER ;RESET POINTER TO 0 RET ;RETURN-NEW RECORD & POINTER POS ; EOFEXIT MVI C,09H ;SELECT PRINT STRING FUNCTION LXI D,EOFMSG ;PASS MESSAGE CALL FDOS ;PRINT EOF MESSAGE JMP BOOT ;RETURN TO CP/M COMMAND LEVEL ;----------------------------------------------------------------------- ; ; THIS SUBROUTINE GETS AN XY PAIR ;AND CONVERTS IT TO RASTER VALUES. THE GENERAL ALGORITHM IS: ; ; INTEGER = (FIXED POINT) * (NUMBER OF RASTERS) * 2/ 2^16 ; ; THE FIXED POINT NUMBER IS A 15 BIT VALUE IN THE RANGE 0 TO 1. ; WHEN VIEWED AS AN INTEGER, THE FIXED POINT COORDINATES RANGE FROM ; 0 TO 32767. WHEN MULTIPLIED BY THE RANGE OF THE RASTER COORDINATES, ; THEY MUST BE DIVIDED BY 32767 TO REPRESENT THE TRUE VALUE. THIS IS ; APPROXIMATED BY MULTIPLYING BY 2 / 65536 (2/64K). DIVIDING BY 64K ; IS ACCOMPLISHED BY SIMPLY DISREGARDING THE LOWER 2 BYTES OF THE RESULT ; ; INPUTS: ; 128 CHARACTER BUFFER @ DMA ; CHARACTER POINTER @ POINTER ; OUTPUTS: ; TWO BYTE VALUE STORED @ X ; TWO BYTE VALUE STORED @ Y ; REGISTER STATUS: ; ALL REGISTER VALUES DESTROYED ; ERROR CONDITIONS: ; NONE- BYTE WILL TERMINATE PROGRAM ON EOF IF NECESSARY ; READXY CALL BYTE ;GET FIRST BYTE OF X PUSH PSW ;STORE FIRST BYTE CALL BYTE ;GET SECOND BYTE MOV B,A ;PUT HIGH BYTE IN [B] POP PSW ;GET LOW BYTE MOV C,A ;[BC] NOW CONTAINS FIXED POINT X COORD. LXI D,MAXX*2 ;PASS MAXIMUM RASTER ADDRESS CALL MULT ;MULTIPLY X COORD BY NO. OF X RASTERS XCHG ;PUT HIGH BYTES IN [HL] SHLD X ;STORE CORRESPONDING RASTER X COORDINATE ; CALL BYTE ;GET FIRST BYTE OF Y PUSH PSW ;STORE FIRST BYTE CALL BYTE ;GET SECOND BYTE MOV B,A ;PUT HIGH BYTE IN [B] POP PSW ;GET LOW BYTE MOV C,A ;[BC] NOW CONTAINS FIXED POINT Y COORD. LXI D,MAXY*2 ;PASS MAXIMUM RASTER ADDRESS CALL MULT ;MULTIPLY Y COORD BY NO. OF Y RASTERS XCHG ;PUT HIGH BYTES IN [HL] SHLD Y ;STORE CORRESPONDING RASTER Y COORDINATE RET ; ;--------------------------------------- ; ; THIS SUBROUTINE ROTATES THE PATTERNS USED FOR ERASING TO A COLOR ; ; INPUTS: ; ARRAY OF 8 PATTERN BYTES STORED AT PATRN ; OUTPUTS: ; ARRAY IS ROTATED ONE BIT DOWN ; REGISTER STATUS: ; [BC],[HL] PRESERVED, ALL OTHERS DESTROYED ; ERROR CONDITIONS: ; NONE ; ROTPAT: PUSH B ;SAVE COUNTER IN [BC] PUSH H ;SAVE POINTER IN [HL] MVI B,8D ;INITIALIZE COUNTER LXI H,PATRN ;INITIALIZE ADDRESS OF HEAD OF ARRAY ROTPT1: MOV A,M ;GET BYTE IF MSBTOP RRC ;ROTATE BYTE ENDIF ;( MSBTOP ) IF NOT MSBTOP RLC ENDIF ;( NOT MSBTOP ) MOV M,A ;STORE ROTATED BYTE ; INX H ;MOVE POINTER TO NEXT BYTE DCR B ;DECREMENT COUNTER JNZ ROTPT1 ;LOOP BACK UNTIL DONE POP H ;RETRIEVE SAVED REGISTERS POP B RET ; ;----------------------------------------------------------------------- ; ; THIS SUBROUTINE INITIALIZES THE VARIABLES USED IN COMPUTING A ; LINE SEGMENT ; ; INPUTS: ; XPOS,YPOS PRESENT POSITION ; X,Y END POINTS OF SEGMENT ; OUTPUTS: ; DX,DY X,Y SIZES OF LINE SEGMENT ; EPSLNX,EPSLNY,SX,SY,DELTA3 INTERNAL VARIABLES ; INITIALIZED ; NI COUNTER USED TO DETERMINE WHEN DONE ; REGISTER SATUS: ; ALL REGISTER VALUES DESTROYED. ; ERROR CONDITIONS: ; NONE ; SEGINIT LHLD X ;GET X XCHG ;PUT X IN DE LHLD XPOS ;PUT PRESENT POS IN HL MOV A,E ;CALCULATE DELTA X SUB L MOV C,A MOV A,D SBB H MOV B,A ;BC NOW CONTAINS DELTA X (DX) LHLD Y ;GET Y END POINT VALUE XCHG ;PUT Y IN DE LHLD YPOS ;GET PRESENT Y POSITION MOV A,E ;CALCULATE DELTA Y (DY) SUB L MOV E,A MOV A,D SBB H MOV D,A ;DE NOW CONTAINS DY XCHG ;PUT DY IN HL, YPOS IN DE SHLD DELTAY ;STORE DY MOV H,B MOV L,C ; SHLD DELTAX ;STORE DELTA X LXI H,0000H ;INITIALIZE VARIABLES SHLD SX SHLD EPSLNY LXI H,0001H SHLD SY SHLD EPSLNX LDA DELTAX+1 ;GET DX HIGH BYTE ORA A ;SET FLAGS ACCORDING TO DX HI BYTE JP CHKDY LXI H,0FFFFH ;CHANGE INITIALIZATION FOR -DX SHLD EPSLNX LHLD DELTAX ;CHANGE SIGN ON DX MOV A,H CMA ;COMPLEMENT HIGH BYTE MOV H,A MOV A,L CMA ;COMPLEMENT LOW BYTE ADI 01H ;ADD 1 TO MAKE IT TWO'S COMP. MOV L,A MOV A,H ACI 00H ;ADD CARRY TO HIGH BYTE MOV H,A SHLD DELTAX ;STORE NOW POSITIVE DX CHKDY LDA DELTAY+1 ;GET DY HIGH BYTE- CONTAINS SIGN ORA A ;SET FLAGS ON DY HI BYTE JP CHDXDY ;DY IS POS- GOTO TRANSPOSE AXES LHLD DELTAY ;DY IS NEGATIVE- CHANGE SIGN MOV A,H CMA ;COMPLEMENT HI BYTE MOV H,A MOV A,L CMA ADI 01H ;COMPLEMENT AND ADD 1 MOV L,A MOV A,H ACI 00H ;ADD CARRY FROM LOW BYTE MOV H,A SHLD DELTAY ;STORE THE NOW POS. DY LXI H,0FFFFH ;LOAD -1 IN (HL) SHLD SY ;SY= -1 CHDXDY LHLD DELTAX ;TRANSPOSE AXES IF DX DY MOV A,E ;HIGH BYTES =, CHECK LOW BYTES CMP L JNC LSTINIT ;IF NO CARRY, DX>= DY- START PLOTTING TNSPOS SHLD DELTAX ;DY WAS IN HL- STORE AS DX XCHG ;DX NOW IN HL, DY NOW IN DE SHLD DELTAY ;STORE OLD DX AS NEW DY LHLD EPSLNX SHLD SX ;REINITIALIZE: SX= EPSILON X LHLD SY SHLD EPSLNY ;EPSILON Y = SY LXI H,0000H SHLD EPSLNX ;EPSILON X = 0 SHLD SY ;SY = 0 ; LSTINIT STC ;CLEAR CARRY -SET=1, THEN COMPLEMENT CMC MOV A,D ;CALCULATE DELTAX/2 BY SHIFTING 1 RIGHT RAR ;SHIFT MOV D,A ;STORE HIGH BYTE DELTAX/2 IN D MOV A,E ;NOW THE LOW BYTE RAR ;SHIFT (DIVIDE BY 2) MOV E,A ;PUT LOW BYTE BACK. XCHG ;PUT DX/2 IN (HL) SHLD DELTA3 ;STORE IN DELTA3 ; LXI H,0001H ;SET NI=1 SHLD NI ;SAVE COUNTER VALUE RET ;DONE WITH INITIALIZATION ; ;------------------------------------------------------------------------ ; STATUS MESSAGE ROUTINE ; ; THIS ROUTINE DISPLAYS A MESSAGE TO INDICATE THAT THE PROGRAM ; IS WORKING. ; ; INPUTS: ; CURRENT COUNT STORED IN STATNO ; OUTPUTS: ; MESSAGE DISPLAYED ; REGISTER STATUS: ; ALL REGISTER VALUES PRESERVED ; ERROR CONDITIONS: ; NONE ; STAT PUSH PSW ;SAVE REGISTERS PUSH B PUSH D PUSH H ; LDA STATNO ;GET COUNTER INR A ;UPDATE COUNTER STA STATNO MVI C,09H ;SELECT WRITE FUNCTION CPI 01H ;SELECT MESSAGE JNZ STATM2 LXI D,STAT1 CALL FDOS ;PRINT MESSAGE JMP STATX ;EXIT SUBROUTINE ; STATM2 CPI 128 ;CHECK FOR OTHER MESSAGE JNZ STATX ;NOT TIME FOR EITHER MESSAGE LXI D,STAT2 CALL FDOS ;PRINT OTHER MESSAGE ; STATX POP H ;RESTORE REGISTERS POP D POP B POP PSW RET ; ;------------------------------------------------------------------------ ; STRING PLOTTING SUBROUTINE ; METHOD: ; ASCII CODE IS STORED REPEATEDLY IN THE AREA OCCUPIED BY ; THE CHARACTER (CWIDTH RASTERS). HI BIT IS SET TO ; INDICATE THAT THE BYTE IS ASCII AND NOT DOT IMAGE. ; ; INPUT: ; X,Y IN FILE BUFFER ; BYTES READ SEQUENTIALLY FROM BUFFER UNTIL CARRIAGE RTN ; IS ENCOUNTERED. ; ; OUTPUTS: ; EACH CHARACTER IS STORED IN THE BYTE CONTAINING THE BIT ; MAP COORDINATE INDICATED FOR THE CHARACTER ; ; REGISTER STATUS: ; ALL REGISTER VALUES DESTROYED ; ; ERROR CONDITIONS: ; X,Y LOCATIONS < 0 ARE RESET TO 0 ; X,Y LOCATIONS > MAX ARE RESET TO 0 ; CR EQU 0DH ;CR = CARRIAGE RETURN STRING CALL READXY ;GET STARTING COORDINATES STRNG0 CALL BYTE ;GET FIRST CHARACTER CPI CR ;IS CHARACTER A CARRIAGE RETURN? RZ ;YES- SO RETURN (ALL DONE) ORI 10000000B ;SET HIGH BIT MOV B,A ;SAVE BYTE IN (B) LHLD X ;GET X LOCATION MOV A,H ;LOOK AT HIGH BYTE ORA A ;SET FLAGS JM RESETX ;X IS NEGATIVE- RESET TO 0 LXI D,MAXX-CWIDTH ;GET MAXIMUM X VALUE CMP D ;COMPARE MAX AND X HIGH BYTES JC STRNG1 ;MAX DEFINITELY > X (X IS OK) JNZ RESETX ;X DEFINITELY > MAX -RESET X MOV A,L ;HI BYTES ARE =: LOOK AT LOW BYTES CMP E ;IS MAX LOW BYTE > X LOW BYTE? JC STRNG1 ;YES IS IS - X IS OK JZ STRNG1 ;LOW BYTES ARE =: X IS BARELY OK RESETX LXI H,0000H ;CLEAR HL SHLD X ;STORE 0 IN X STRNG1 LHLD Y ;FETCH Y STARTING LOCATION MOV A,H ;LOOK AT Y HIGH BYTE ORA A ;SET FLAGS JM RESETY ;NEGATIVE - RESET TO 0 LXI D,MAXY ;USE ENTIRE COORDINATE RANGE FOR Y CMP D ;COMPARE MAX AND Y HIGH BYTES JC STRNG2 ;Y DEFINITELY OK JNZ RESETY ;Y DEFINITELY > MAX - RESET Y MOV A,L ;HI BYTES ARE =: LOOK @ LOW BYTES CMP E ;COMPARE MAX AND Y LOW BYTES JC STRNG2 ;MAX > Y - Y IS OK JZ STRNG2 ;Y = MAX RESETY LXI H,0000H ;CLEAR OLD VALUE OF Y SHLD Y ;Y = 0 STRNG2 XCHG ;PUT Y IN (DE) LHLD X ;FETCH X PUSH B ;SAVE BYTE TEMPORARILY PUSH D ;SAVE Y COORD TEMPORARILY ; MAKE X COORD. A MULTIPLE OF CWIDTH FOR PROPER PRINTER OUTPUT SHLD DIVDND ;COMPUTE X=(X/CWIDTH)*CWIDTH MVI A,CWIDTH ;GET CWIDTH FOR DIVISOR STA DIVSOR CALL DIVIDE ;DIVIDE X BY CWIDTH LDA QOTENT ;GET RESULTS (NO OVERFLOW AS 0<=X<1530) LXI B,CWIDTH ;PASS CHARACTER WIDTH CALL BMULT ;[HL] NOW CONTAINS (X/CWIDTH)*CWIDTH ; MOV B,H ;PUT X IN (BC) MOV C,L POP D ;RETRIEVE Y COORDINATE LXI H,MAXY ;PUT MAX Y IN (HL) CALL LOCDOT ;GET LOCATION OF BYTE POP B ;RETRIEVE BYTE MOV M,B ;PUT BYTE IN ADDRESS CONTAINING X,Y ; STORE BYTE REPEATEDLY TO BLANK OUT ENTIRE AREA OCCUPIED BY IT MVI A,CWIDTH-1 ;INITIALIZE LOOP COUNTER STRNG3: INX H ;INCREMENT ADDRESS MOV M,B ;STORE BYTE SUI 1 ;DECREMENT LOOP COUNTER JNZ STRNG3 ;LOOP BACK UP UNTIL FINISHED MVI C,CWIDTH ;PUT CWIDTH IN (C) LHLD X ;FETCH X LOCATION MVI B,00H ;CLEAR (B) DAD B ;INCREMENT X LOCATION FOR NEXT CHARACTER SHLD X ;STORE NEW X LOCATION JMP STRNG0 ;LOOP UP TO TOP ; ;----------------------------------------------------------------------- ; TEXT ; ; THIS SUBROUTINE OUTPUTS TEXT IMMEDIATELY TO THE PRINTER ; NOTE: TEXT IS NOT PUT INTO MEMORY MAP ; ; INPUTS: ; TEXT STRING IN FILE (ENDS WITH 0 BYTE) ; OUTPUTS: ; TEXT STRING PRINTED ; REGISTER STATUS: ; ALL REGISTER VALUES DESTROYED ; ERROR CONDITIONS: ; NONE PECULIAR TO THIS ROUTINE ; TEXT CALL BYTE ;GET NEXT CHARACTER CPI 0 ;CHECK FOR END OF STRING RZ ;RETURN IF FINISHED ; MOV E,A ;PASS CHARACTER MVI C,05 ;SELECT CP/M LST: OUTPUT CALL PDOS ;PRINT IT ; JMP TEXT ;LOOP BACK UNTIL DONE ; ;----------------------------------------------------------------------- ; ; THIS SUBROUTINE UPLOADS THE ARRAY DEFINING COLOR PALLET ; ; INPUTS: ; 16 BIT INTEGER SPECIFYING # OF DATA BYTES TO COME ; DATA BYTES IN INPUT FILE ; OUTPUTS: ; NEW COLOR VALUES STORED IN APPROPRIATE ARRAYS ; REGISTER STATUS: ; ALL REGISTER VALUES DESTROYED ; ERROR CONDITIONS: ; NONE ; UPLOAD: CALL BYTE ;GET LOW BYTE OF INTEGER MOV C,A ;SAVE INTEGER IN [BC] CALL BYTE ;GET HIGH BYTE ; ORA A ;CHECK VALUE OF HIGH BYTE JNZ UPBAD ;FOR THIS PROGRAM, HI BYTE MUST BE 0 MOV A,C ;LOOK AT LOW BYTE CPI 7D ;7 INDICATES UPLOAD PLAID PATTERNS JZ UPLAID ;PROCEED TO UPLOAD PLAID VALUES CPI 64D ;64 INDICATES UPLOAD DITHER MATRIX JZ UPDITH ;PROCEED TO UPLOAD DITHER MATRIX CPI 120D ;124 INDICATES UPLOAD SPECIAL PATTERNS JZ UPCIF ;PROCEED TO UPLOAD SPECIAL PATTERNS ; UPBAD: CALL BYTE ;# HAS UNEXPECTED VALUE- SKIP BYTES DCX B ;DECREMENT LOOP COUNTER MOV A,C ORA B ;IS COUNTER = 0 ? JNZ UPBAD ;LOOP BACK UNTIL FINISHED RET ; UPLAID: LXI H,PLAIDS+1 ;POINT TO PLAID ARRAY (LEAVE "0" ALONE) JMP UPLP1 ;PROCEED TO READ-STORE LOOP UPCIF: LXI H,CIFPAT ;SET POINTER AT START OF SPECIAL PATTERNS JMP UPLP1 UPDITH: LXI H,DITHARR ;POINT TO DITHER ARRAY UPLP1: CALL BYTE ;GET COLOR PATTERN MOV M,A ;STORE PATTERN INX H ;POINT TO NEXT PATTERN SLOT DCR C ;DECREMENT COUNTER JNZ UPLP1 ;LOOP BACK UNTIL FINISHED RET ; ;----------------------------------------------------------------------- ; THIS SUBROUTINE IS EXECUTED WHEN OVERFLOW OCCURS IN MULT. OR DIV ; INPUTS: ; NONE ; OUTPUTS: ; MESSAGE "OVERFLOW" ; ALL REGISTERS PUSHED ON STACK ; IN ORDER: PSW, H, D, B ; FINAL POSITION OF STACK POINTER SAVED IN OLDSTK ; REGISTER STATUS: ; ALL INPUT REGISTERS STORED ON STACK, C, DE, HL REG CHANGED ; ERROR CONDITIONS: ; NONE ; WOOPS PUSH PSW ;SAVE ALL REGISTERS PUSH H PUSH D PUSH B LXI H,0000H ;CLEAR (HL) DAD SP ;GET STACK POINTER SHLD OLDSTK ;SAVE STACK POINTER FOR DEBUG MVI C,09H ;SELECT PRINT FUNCTION LXI D,OVFLMSG CALL FDOS ; PRINT 'OVERFLOW' JMP BOOT ;RETURN TO CP/M COMMAND LEVEL OVFLMSG DB 'OVERFLOW$' ; ;----------------------------------------------------------------------- ; WRITE RECORD SUBROUTINE ; ; INPUTS: ; OPENED FILE ; FILE CONTROL BLOCK @ FCB2 ; BUFFER @ DMA2 ; BUFFER POINTER @ POINTR2 ; OUTPUTS: ; BUFFER WRITTEN TO FILE ; BUFFER POINTER RESET TO 0 ; REGISTER STATUS: ; ALL REGISTER VALUES CHANGED ; ERROR CONDITIONS: ; IF NO SPACE LEFT ON DISK, ERROR MESSAGE WRITTEN ; AND PROGRAM TERMINATES. ; WRITE MVI C,26D ;SELECT SET DMA FUNCTION LXI D,DMA2 ;PASS O/P BUFFER CALL FDOS ;SET DMA ADDRESS ; MVI C,21D ;SELECT WRITE SEQUENTIAL LXI D,FCB2 ;PASS O/P FCB CALL FDOS ;WRITE RECORD ; CPI 00H ;WAS WRITE OK? JNZ FULLXIT ;JUMP TO ERROR SECTION IF NOT MVI A,00H ;CLEAR (A) STA POINTR2 ;POINTR2=0 RET ;DONE WITH SUCCESSFUL WRITE FULLXIT MVI C,09D ;SELECT PRINT FUNCTION LXI D,NOROOM ;PASS ERROR MESSAGE CALL FDOS ;PRINT IT ; JMP BOOT ;TERMINATE WITH WARM START ; ;----------------------------------------------------------------------- ; ; THIS SUBROUTINE IS USED FOR NON-STANDARD EXTENSIONS TO PLOT ; ; INPUTS: ; NONE ; OUTPUTS: ; NONE ; REGSISTER STATUS: ; ALL VALUES PRESERVED ; ERROR CONDITIONS: ; NONE ; XTEND: PUSH PSW PUSH B PUSH D PUSH H ; CALL BYTE ;GET LOW BYTE OF NUMBER OF DATA BYTES MOV A,C CALL BYTE ;GET HIGH BYTE OF NUMBER OF BYTES MOV A,B ;[BC] IS NOW 16 BIT INTEGER ORA C ;IS NUMBER = 0? JZ XTND2 ;FINISHED IF N = 0 XTND1: CALL BYTE ;GET DATA BYTE DCX B ;DECREMENT COUNTER MOV A,C ORA B ;IS COUNTER = 0 ? JNZ XTND1 ;LOOP BACK IF MORE TO COME XTND2: POP H ;RESTORE REGISTERS POP D POP B POP PSW RET ;FINISHED ; ;----------------------------------------------------------------------- ; ORIGIN ;START OF PICTURE MAP ; ;-----------------------------------------------------------------------