.TITLE MACPLOT Routines for matrix-based plotter .SBTTL Summary & Description ;++ ; MACPLOT.MAR: ; ; VAX-11 MACRO routines for VPLOT: ; by ; M. Gooley ; Millikin University Computer Center ; Decatur, Illinois 62522 ; ; Copyright (C) 1981 by M. Gooley. This software is ; distributed without cost, and may be reproduced only ; with the inclusion of this copyright statement. The ; author assumes no responsibility for the performance ; of this software. ; ; These routines do the dirty work for the VPLOT matrix- ; based plotter: they provide the illusion of a huge matrix of ; individually-addressable bits, each corresponding to one dot of ; a PRINTRONIX plot, whilst actually fetching 120-byte blocks of ; virtual memory only as needed (using the LIB$GET_VM library ; procedure). Much virtual memory is thereby saved, though at the ; expense of CPU time; each block also requires a longword pointer ; to its base-address, which "wastes" four bytes per block. ; ;-- .SBTTL Data area .PSECT SMALLDAT,NOEXE WIDTH: .LONG ;width of plot in blocks WTH4: .LONG ; ...times 4 WTH4M1: .LONG ; ...and minus 1: last character in line LENGTH: .LONG ; length of plot in blocks AREA: .LONG ; 4 times # of blocks--# of bytes in ; table of base-addresses TABEND: .LONG ; end of table of base-addresses BLKTAB: .LONG ; base of table of block base-addresses EORBLK: .LONG ; last block of current row (in DUMP) BITROW: .LONG 0 ; counter for row within block (in DUMP) BLKSIZE:.LONG 120 ; size of blocks, in bytes LASTADR:.LONG ; address of last-row indicator STRBASE:.LONG ; address of base-string STRLEN: .LONG ; address of string-length .SBTTL The Macros .PSECT MACPORTION,NOWRT .MACRO OUTEST REG,BOUND TSTL REG ;test register BLSS OUT ; branch to OUT if less than zero CMPL REG,BOUND ; compare register with BOUND BGEQ OUT ; branch to OUT if equal or greater .ENDM OUTEST .MACRO FREEBLK BASE,SIZE PUSHL BASE ; push register containing address of ; memory-block PUSHAL SIZE ; push addr. of longw. containing size CALLS #2,LIB$FREE_VM ; return the memory block ; take no action if it's not wanted back .ENDM FREEBLK .SBTTL Initialisation Routine .PSECT INITIAL,NOWRT .ENTRY INITIAL,^M ; entry mask (R0-R5 are zapped by the ; MOVC5 instruction at the end of the ; routine... MOVL 4(AP),R2 ; width to R2 MOVL 8(AP),R3 ; length to R3 (arguments passed ; by-value) MOVL 12(AP),LASTADR ; address of last-row indicator ; (by-reference) MOVL 16(AP),STRLEN ; address of string return-length MOVL 28(AP),STRBASE ; address of string base ; (by reference) MULL3 R2,R3,R4 ; # of blocks to R4 MULL3 #4,R4,AREA ; 4 times that many bytes needed LOOP1: PUSHAL BLKTAB ; location to receive addr. of block PUSHAL AREA ; # of bytes requested CALLS #2,G^LIB$GET_VM ; allocate memory BLBC R0,LOOP1 ; try again if memory unavailable MOVL R2,WIDTH ; store width MULL2 #4,R2 ; calculate 4 times width MOVL R2,WTH4 ; store it SUBL3 #1,R2,WTH4M1 ; decrement it and store that MOVL R3,LENGTH ; store length ADDL3 BLKTAB,AREA,TABEND SUBL2 #4,TABEND ; decrement to get actual location ; TABEND=end of block-address table ADDL3 WTH4,BLKTAB,EORBLK SUBL2 #4,EORBLK ; initialise EORBLK to last block of ; first row MOVC5 #0,STRLEN,#0,AREA,@BLKTAB ; clear table of base-addresses RET .SBTTL Matrix-loading routine .PSECT LOAD .ENTRY LOAD,^M ; entry mask CLRL R3 ; clear R3 for coming EDIV MOVL 8(AP),R2 ; X-coord. to R2+R3 EDIV #40,R2,R4,R7 ; X of block to R4, X-bit in block to R7 OUTEST R4,LENGTH ; X<0 or X>=LENGTH? If so, go to OUT MOVL 4(AP),R2 ; Y-coord. to R2+R3 EDIV #24,R2,R6,R8 ; Y of block to R6, Y-bit in block to R8 OUTEST R6,WIDTH ; Y<0 or Y>=WIDTH? If so, go to OUT MULL2 WIDTH,R4 ; calculate the actual... ADDL2 R4,R6 ; ...number of the block... MULL2 #4,R6 ; ...and its displ. from table base ADDL2 BLKTAB,R6 ; ...and the address of its base address MULL2 #3,R7 ; calculate base byte of field TSTL (R6) ; does the block exist? (is it <>0?) BNEQ DOT ; if it exists, go to DOT LOOP2: PUSHL R6 ; address of base-address of block PUSHAL BLKSIZE ; push blocksize address CALLS #2,G^LIB$GET_VM ; allocate memory BLBC R0,LOOP2 ; try again if there isn't any MOVC5 #0,STRBASE,#0,BLKSIZE,@0(R6) ; clear new block (STRBASE serves as a ; dummy address) DOT: INSV #1,R8,#1,@0(R6)[R7] ; insert bit at desired location OUT: RET .SBTTL Output routine .PSECT DUMP,NOWRT .ENTRY DUMP,^M ; entry mask MOVC5 #0,STRBASE,#64,#133,@STRBASE MOVL #1,R2 ; set end-of-line flag (R2) MOVL EORBLK,R3 ; last block of row to R3 MOVL WTH4M1,R4 ; character counter set to max. (R4) MULL3 #3,BITROW,R5 ; base-byte of blocks for this line CLRL @STRLEN ; clear string-length buffer 10$: MOVL #18,R6 ; bit-field counter 20$: TSTL (R3) ; does the block exist? BNEQ 40$ ; if so, go to 40$ ACBB #0,#-4,R4,25$ ; subtract 4 from R4; goto 25$ if >0 BRW 60$ ; BLSS 60$ impossible (displ. too large) 25$: SUBL2 #4,R3 ; point R3 to address of next block BRB 20$ ; check next block 40$: EXTZV R6,#6,@0(R3)[R5],R7 ; extract value and put it in R7 BEQL 52$ ; if R7=0 go to 52$ BLBC R2,45$ ; skip next bit if R2 clear ADDL3 #1,R4,R8 ; index for plot-indicator CLRL R2 ; clear R2 flag ;************************************************************************ ;************************************************************************ ;*****THE FOLLOWING THREE LINES OF CODE SHOULD BE DELETED IF YOUR******** ;*****PRINTER'S DEVICE HANDLER PASSES THE CHARACTER. SEE********** ;*****THE VPLOT GUIDE FOR FURTHER INFORMATION...************************* ;************************************************************************ 45$: CMPL #63,R7 ; contents of field=63? BNEQ 50$ ; if not, skip next part MOVL #191,R7 ; substitute 191 for the field's content ;************************************************************************ ;************************************************************************ 50$: ADDL2 #64,R7 ; set the #7 bit required for plot-mode MOVB R7,@STRBASE[R4] ; move data byte to the character-string 52$: DECL R4 ; next character BLSS 57$ ; branch to 57$ if out of characters ACBB #0,#-6,R6,40$ ; decrement field-counter; to 40$ if>=0 CMPL BITROW,#39 ; does BITROW indicate that this is the ; last row in the block? BNEQ 55$ ; if not, skip this next part FREEBLK R3,BLKSIZE ; call macro to return the block's ; memory 55$: SUBL2 #4,R3 ; move block-counter to next block BRW 10$ ; branch to 10$ 57$: CMPL #39,BITROW ; last row in block? BNEQ 60$ ; if not, to 60$ FREEBLK R3,BLKSIZE ; else, return block 60$: INCL BITROW ; next bit-row CMPL #40, BITROW ; BITROW=40? BNEQ 70$ ; exit if not, else... CLRL BITROW ; BITROW=0 ADDL2 WTH4,EORBLK ; set EORBLK to end of next line CMPL EORBLK,TABEND ; beyond end of block-table? BLEQ 70$ ; exit if not CLRB @LASTADR ; set end-of-plot indicator MOVL BLKTAB,R3 FREEBLK R3,AREA ; return block-table 70$: BLBC R2,LEAVE MOVL R2,R8 LEAVE: MOVB #5,@STRBASE[R8] ADDL3 #1,R8,@STRLEN RET .END