Classic Computer Magazine Archive PROGRAM LISTING: 88-05b/SPOOLER.M65


0100 ; PRINTER SPOOLER
0110 ; BY GLENN K. SMITH
0120 ; (c)1988, ANTIC PUBLISHING
0130     .OPT NO LIST
0140     .OPT OBJ
0150 ;
0160 DOSVEC = $0A    ;DOS VECTOR
0170 DOSINI = $0C    ;DOS INIT
0180 DEST =  $CC     ;DEST ADDRESS
0190 SOURCE = $CE    ;SOURCE ADDRESS
0200 VVBLKD = $0224  ;VBI ADDRESS
0210 DDEVIC = $0300  ;DEVICE ID
0220 HATABS = $031A  ;HANDLER TABLE
0230 PRBUFF = $03C0  ;PRINTER BUFFER
0240 MEMLO = $02E7   ;MEMLO POINTER
0250 SMOVE = $44AE   ;START OF MOVER
0260 SPOOLER = $4500 ;SPOOLER ADDR
0270 SPOOL1 = $4600  ;SPOOLER+$100
0280 SPOOL2 = $4700  ;SPOOLER+$200
0290 BUFEND = $66B0  ;END OF BUFFER
0300 SIOV =  $E459   ;SIOV VECTOR
0310 SETVBV = $E45C  ;VBV SET ROUTINE
0320 XITVBV = $E462
0330 ;
0340 ; +---------------------------+
0350 ; | This is the relocator part|
0360 ; |  of PRINTER SPOOOLER. It  |
0370 ; | will move the program to  |
0380 ; | the lowest point possible |
0390 ; |  in memory, then run the  |
0400 ; |      PRINTER SPOOLER.     |
0410 ; +---------------------------+
0420 ;
0430     *=  SMOVE   ;START PROGRAM
0440 ;
0450 BOOT
0460     LDY MEMLO+1 ;GET NEW ADDRESS
0470     INY         ;MAKE NEXT EVEN NUMBER
0480     STY DEST+1  ;SAVE IT
0490 ;
0500     LDY #$00    ;CLEAR LSB
0510     STY DEST
0520     STY SOURCE
0530 ;
0540     LDA # >OLDMEM ;START OF SPOOLER
0550     STA SOURCE+1
0560 ;
0570 RELOC
0580     LDX MEMLO+1 ;USED TO FIGURE NEW ADDR
0590     LDA (SOURCE),Y ;MOVE SPOOLER
0600     CMP # >BUFEND ;BUFEND MSB
0610     BEQ FIXEND  ;YES, FIX IT
0620 ;
0630     CMP # >SPOOLER ;SPOOLER ADDRESS?
0640     BEQ ZERO    ;YES, IN FIRST 256 BYTES
0650 ;
0660     CMP # >SPOOL1 ;SPOOLER ADDRESS?
0670     BEQ ONE     ;YES, IN SECOND 256 BYTES
0680 ;
0690     CMP # >SPOOL2 ;SPOOLER ADDRESS?
0700     BNE RELSTOR ;NO, SAVE AS IS
0710 ;
0720 FIXEND
0730     TXA         ;FIX MSB OF BUFEND
0740     CLC 
0750     ADC #$21
0760     BNE RELSTOR
0770 ;
0780 TWO
0790     INX         ;ADDR IS 512 BYTES FROM ORG
0800 ONE
0810     INX         ;ADDR IS 256 BYTES FROM ORG
0820 ZERO
0830     INX         ;ADD 1 BECAUSE THE MSB OF MEMLO
0840     TXA         ;HAD 1 ADDED TO IT
0850 ;
0860 RELSTOR
0870     STA (DEST),Y ;SAVE BYTE
0880     INC DEST    ;GET NEXT ADDRESS
0890     INC SOURCE
0900     BNE EXAMINE ;NOT ZERO
0910 ;
0920     INC DEST+1  ;INC MSB
0930     INC SOURCE+1
0940 ;
0950 EXAMINE
0960     LDA SOURCE+1 ;ALL DONE?
0970     CMP # >FINI
0980     BNE RELOC   ;NO GET MORE
0990 ;
1000     LDA SOURCE  ;LSB THE SAME?
1010     CMP # <FINI
1020     BNE RELOC   ;NO, MORE
1030 ;
1040     LDX MEMLO+1 ;GET ADDRESS TO JUMP TO
1050     INX 
1060     INX 
1070     STX BOOTIT+2
1080 BOOTIT
1090     JMP START   ;CALL SPOOLER
1100 ;
1110 ; +---------------------------+
1120 ; |  This is the main PRINTER |
1130 ; | SPOOLER program that will |
1140 ; |   be relocated in memory  |
1150 ; +---------------------------+
1160 ;
1170 ;+----------------------------+
1180 ;|   Storage used by Spooler  |
1190 ;+----------------------------+
1200 ;
1210 OLDMEM
1220     .BYTE $00,$00 ;OLD MEMLO VALUE
1230 OLDVVB
1240     .BYTE $00,$00 ;OLD VBI ADDRESS
1250 OLDHAND
1260     .BYTE $00,$00 ;OLD P: HANDLER ADDRESS
1270 INDEX
1280     .BYTE $00   ;PRINT BUFFER INDEX
1290 STATUS
1300     .BYTE $01   ;PRINT STATUS
1310 PRIORITY
1320     .BYTE $00   ;WHO DOES WHAT WHEN
1330 CHAR
1340     .BYTE $00   ;CHAR TO BE PRINTED
1350 IOCB
1360     .BYTE $00   ;DEVICE NUMBER
1370 COUNT
1380     .BYTE $00,$00 ;NUMBER OF CHARACTERS
1390 ;
1400 ;+----------------------------+
1410 ;|   P: HANDLER PUT ROUTINE   |
1420 ;|This will store a character |
1430 ;|  into the printer buffer   |
1440 ;+----------------------------+
1450 ;
1460 PUTCHAR
1470     STA CHAR    ;SAVE CHAR TO BE PRINTED
1480     STX IOCB    ;SAVE CHANNEL
1490     LDA COUNT   ;ANY CHARACTERS YET?
1500     ORA COUNT+1
1510     BEQ STORE   ;NO, BUFFER EMPTY
1520 ;
1530 WAIT
1540     LDA INPUT+1 ;BUFFER FULL?
1550     CMP OUTPUT+1
1560     BNE STORE   ;NO, SOME SPACE LEFT
1570 ;
1580     LDA INPUT+2 ;MAYBE?
1590     CMP OUTPUT+2
1600     BNE STORE   ;YES, WAIT UNTIL SOME PRINTED
1610 ;
1620     LDA #$00
1630     STA PRIORITY ;FORCE PRINT
1640     BEQ WAIT
1650 ;
1660 STORE
1670     LDA CHAR    ;GET CHAR
1680 INPUT
1690     STA BUFFER  ;SAVE IT
1700 ;
1710     INC COUNT   ;UPDATE LSB OF CHAR COUNTER
1720     BNE BUMPIN  ;NO CARRY
1730     INC COUNT+1 ;UPDATE MSB PART OF COUNTER
1740 ;
1750 BUMPIN
1760     INC INPUT+1 ;MOVE INPUT POINTER
1770     BNE CHECKIN ;NO CARRY
1780     INC INPUT+2 ;ADD CARRY TO MSB OF POINTER
1790 ;
1800 CHECKIN
1810     LDA INPUT+2 ;ROUND POINTER TO START OF BUFFER?
1820     CMP # >BUFEND
1830     BNE EXITPUT ;NO
1840 ;
1850     LDA INPUT+1 ;MAYBE?
1860     CMP # <BUFEND
1870     BNE EXITPUT ;NO, NOT YET
1880 ;
1890     LDA # <BUFFER ;ROUND TO START OF BUFFER
1900     LDX # >BUFFER
1910     STA INPUT+1
1920     STX INPUT+2
1930 ;
1940 EXITPUT
1950     LDX IOCB    ;RESTORE IOCB IF NEEDED
1960     LDY #$01    ;PRINT WAS GOOD
1970     STY PRIORITY ;PUT ROUTINE HAS PRIORITY
1980     RTS 
1990 ;
2000 ;+----------------------------+
2010 ;|  This is the PRINT routine |
2020 ;|that is called by the VVBLKD|
2030 ;|  every 1/60th of a second  |
2040 ;+----------------------------+
2050 ;
2060 ; +---------------------------+
2070 ; |  If the priority flag=1   |
2080 ; | then the PUT CHAR routine |
2090 ; |  will have priority over  |
2100 ; | the print routine. If the |
2110 ; | PUT CHAR is done, then the|
2120 ; | VBI print routine has will|
2130 ; |  print a character every  |
2140 ; |    sixtieth of a second.  |
2150 ; +---------------------------+
2160 ;
2170 NEWVBI
2180     LDA PRIORITY ;OK TO RUN?
2190     BEQ SEESTAT ;YES, ATTEMPT PRINT
2200 ;
2210     DEC PRIORITY ;SET TO VBI PRIORITY
2220     JMP XITVBV  ;IF NO CHANGE, PRINT NEXT TIME
2230 ;
2240 SEESTAT
2250     LDA STATUS  ;PRINT OK?
2260     BPL VBICALL ;YES, MOVE CHARS
2270 ;
2280     JMP PRINT   ;NO, RE-TRY BUFFER
2290 ;
2300 VBICALL
2310     LDA COUNT   ;ANY CHARS TO BE PRINTED?
2320     ORA COUNT+1
2330     BNE ISCHARS ;YES
2340 ;
2350     JMP FINISHED ;NO, EXIT
2360 ;
2370 ISCHARS
2380     LDX INDEX   ;GET BUFFER INDEX
2390 OUTPUT
2400     LDA BUFFER  ;GET CHAR TO BE PRINTED
2410     STA PRBUFF,X
2420     TAY         ;SAVE IT
2430     INC OUTPUT+1 ;MOVE OUTPUT POINTER TO
2440     BNE CHECKOUT ;NEXT CHAR
2450     INC OUTPUT+2 ;ADD CARRY TO MSB OF POINTER
2460 ;
2470 CHECKOUT
2480     LDA OUTPUT+2 ;ROUND OUTPUT BUFFER?
2490     CMP # >BUFEND
2500     BNE SUBTRACT ;NO, NOT YET
2510 ;
2520     LDA OUTPUT+1 ;MAYBE?
2530     CMP # <BUFEND
2540     BNE SUBTRACT ;NO, NOT NEED YET
2550 ;
2560     LDA # <BUFFER ;ROUND OUTPUT POINTER TO
2570     LDX # >BUFFER
2580     STA OUTPUT+1
2590     STX OUTPUT+2
2600 ;
2610 SUBTRACT
2620     LDA COUNT   ;COUNT DOWN THE CHAR COUNTER
2630     BNE DECLSB  ;LSB NOT TO ZERO
2640 ;
2650     DEC COUNT+1 ;DO THE MSB OF THE COUNTER TOO
2660 DECLSB
2670     DEC COUNT   ;DO THE LSB OF THE COUNTER
2680     INX         ;MOVE PRINT BUFFER INDEX
2690     STX INDEX   ;SAVE IT
2700     CPX #40     ;40 CHARS YET?
2710     BEQ SETPRNT ;YES, FLUSH PRINT BUFFER
2720 ;
2730     CPY #155    ;A EOL?
2740     BNE FINISHED ;NO, GET MORE CHARS
2750 ;
2760     LDA #$20    ;PADD BUFFER IF EOL
2770 FILL
2780     STA PRBUFF,X
2790     INX         ;ADD 1 TO THE COUNTER
2800     CPX #40     ;40 CHARACTERS YET?
2810     BNE FILL    ;NO, PADD MORE BLANKS
2820 ;
2830 ; +---------------------------+
2840 ; |   SETPRNT tells the VBI   |
2850 ; |   routine that the last   |
2860 ; | was bad. This allows the  |
2870 ; |   the computer to print   |
2880 ; | during the next interrupt |
2890 ; |  instead of doing it all  |
2900 ; |   during one interrupt.   |
2910 ; +---------------------------+
2920 ;
2930 ; I could have used any number greater than
2940 ; 127. I picked $92 because it was handy, and
2950 ; had some meaning.
2960 ;
2970 SETPRNT
2980     LDY #$92    ;FUNCTION NOT IMPLEMENTED
2990     JMP QUIT    ;SAVE RESULT
3000 ;
3010 ; +---------------------------+
3020 ; | This is the actual printer|
3030 ; |  part of PRINTER SPOOLER. |
3040 ; | It will save the old SIO  |
3050 ; | DCB, print the buffer, and|
3060 ; | restore the SIO DCB back. |
3070 ; +---------------------------+
3080 ;
3090 PRINT
3100     LDX #$0B    ;SAVE SIO DCB
3110 SAVEDCB
3120     LDA DDEVIC,X
3130     STA OLDDCB,X
3140     DEX         ;ALL DONE YET?
3150     BPL SAVEDCB ;NOPE, STILL SOME LEFT
3160 ;
3170     LDX #$0B    ;SETUP SIO DCB
3180 PMOVE
3190     LDA SIODAT,X ;MY PRINT DATA
3200     STA DDEVIC,X ;SAVE SO COMPUTER WILL KNOW
3210     DEX         ;ANY MORE TO MOVE?
3220     BPL PMOVE   ;YES, SOME LEFT
3230 ;
3240     INX         ;MAKE 0
3250     STX INDEX   ;SAVE BUFFER OFFSET
3260     JSR SIOV
3270 ;
3280     LDX #$0B    ;RESTORE SIO DCB
3290 REPLACE
3300     LDA OLDDCB,X ;GET THE OLD INFO
3310     STA DDEVIC,X ;AND REPLACE IT. JUST IN CASE!
3320     DEX         ;ALL DONE WITH REPLACMENT?
3330     BPL REPLACE ;NO, STILL A FEW TO REPLACE
3340     .BYTE $2C   ;TRICK, SKIP NEXT INSTRUCTION
3350 ;
3360 FINISHED
3370     LDY #$01    ;SAY PRINT WAS GOOD
3380 QUIT
3390     STY STATUS  ;PRINT STATUS
3400     JMP XITVBV  ;EXIT VVBLKD
3410 ;
3420 ; +---------------------------+
3430 ; |  This is the information  |
3440 ; | that is needed by the SIO |
3450 ; |    to attempt a print.    |
3460 ; +---------------------------+
3470 ;
3480 SIODAT
3490     .BYTE $40   ;P:
3500     .BYTE $01   ;#1
3510     .BYTE $57   ;WRITE
3520     .BYTE $80   ;OUTPUT
3530     .BYTE $C0   ;PRINT BUFFER LSB
3540     .BYTE $03   ;PRINT BUFFER MSB
3550     .BYTE $1E   ;DEVICE TIMEOUT
3560     .BYTE $00   ;NOT USED
3570     .BYTE $28   ;40 CHARS
3580     .BYTE $00   ;NOT USED
3590     .BYTE $4E   ;NORMAL MODE
3600     .BYTE $00   ;NOT USED
3610 ;
3620 ; +---------------------------+
3630 ; | Temporary storage for the |
3640 ; |   SIO DCB. Contains the   |
3650 ; |  values before the print  |
3660 ; |        was attempted.     |
3670 ; +---------------------------+
3680 ;
3690 OLDDCB
3700     .BYTE $00,$00,$00,$00,$00,$00
3710     .BYTE $00,$00,$00,$00,$00,$00
3720 ;
3730 ; +---------------------------+
3740 ; |  This the new DOS vector. |
3750 ; |  It will replace the old  |
3760 ; |  values and disable the   |
3770 ; |  PRINT SPOOLER. All output|
3780 ; | to the printer will stop. |
3790 ; +---------------------------+
3800 ;
3810 NEWDOS
3820     LDA CALLDOS+1 ;REPLACE DOSVEC
3830     LDX CALLDOS+2
3840     STA DOSVEC  ;SAVE OLD VECTOR
3850     STX DOSVEC+1
3860 ;
3870     LDA RESET+1 ;REPLACE DOSINI
3880     LDX RESET+2
3890     STA DOSINI  ;SAVE OLD DOSINI
3900     STX DOSINI+1
3910 ;
3920     LDA OLDMEM  ;REPLACE MEMLO
3930     LDX OLDMEM+1
3940     STA MEMLO   ;SAVE OLD MEMLO VALUE
3950     STX MEMLO+1
3960 ;
3970     LDA OLDHAND ;REPLACE P: HANDLER
3980     LDX OLDHAND+1
3990     STA HATABS+1 ;SAVEE THE OLD HANDLER
4000     STX HATABS+2
4010 ;
4020     LDY OLDVVB  ;REPLACE VVBLKD
4030     LDX OLDVVB+1
4040     LDA #$07
4050     JSR SETVBV  ;REMOVE THE VVBLKD
4060 ;
4070 CALLDOS
4080     JMP CALLDOS ;CALL OLD DOSVEC
4090 ;
4100 ; +---------------------------+
4110 ; |  This is the RESET trap   |
4120 ; | routine. It will make sure|
4130 ; | that the SPOOLER is ready |
4140 ; | to handle data when needed|
4150 ; +---------------------------+
4160 ;
4170 RESET
4180     JSR DOSINI  ;INITIALIZE DOS
4190 SETDOS
4200     LDA # <NEWDOS ;TRAP DOS VECTOR
4210     LDX # >NEWDOS
4220     STA DOSVEC  ;MAKE SURE DOSVECTOR IS SET
4230     STX DOSVEC+1
4240 ;
4250     LDA # <BUFFER ;RESET TO START OF BUFFER
4260     LDX # >BUFFER
4270     STA INPUT+1 ;INPUT BUFFER
4280     STX INPUT+2
4290     STA OUTPUT+1 ;OUTPUT BUFFER
4300     STX OUTPUT+2
4310 ;
4320     LDA # <BUFEND ;SAVE SOME MEMORY FOR THE BUFFER
4330     LDX # >BUFEND
4340     STA MEMLO   ;TELL THE COMPUTER
4350     STX MEMLO+1
4360 ;
4370     LDA # <OPEN ;POINT P: TO MY HANDLER
4380     LDX # >OPEN
4390     STA HATABS+1 ;STUFF IT IN THE HANDLER TABLE
4400     STX HATABS+2
4410 ;
4420     LDY #$00    ;CLEAR COUNTER
4430     STY COUNT   ;CLEAR THE LSB
4440     STY COUNT+1 ;CLEAR THE MSB
4450     STY INDEX   ;CLEAR PRINT BUFFER INDEX
4460 ;
4470     INY         ;SET TO 1
4480     STY STATUS  ;SET PRINTER STATUS
4490 ;
4500     LDY # <NEWVBI ;INIT VBI PRINT ROUTINE
4510     LDX # >NEWVBI
4520     LDA #$07
4530     JMP SETVBV
4540 ;
4550 ; +---------------------------+
4560 ; |  This will be the new P:  |
4570 ; | handler vector table. The |
4580 ; | only change is in the way |
4590 ; | the P: device will print. |
4600 ; +---------------------------+
4610 ;
4620 OPEN
4630     .BYTE $00,$00 ;OPEN P:
4640 CLOSE
4650     .BYTE $00,$00 ;CLOSE P:
4660 GET
4670     .BYTE $00,$00 ;GET P:
4680 PUT
4690     .WORD PUTCHAR-1 ;PUT P:
4700 STATS
4710     .BYTE $00,$00 ;STATUS P:
4720 SPECIAL
4730     .BYTE $00,$00 ;WHATEVER
4740 INIDEV
4750     .BYTE $00,$00,$00 ;INITIALIZE P:
4760 ;
4770 BUFFER
4780     .BYTE $00   ;START OF BUFFER
4790 ;
4800 ; +---------------------------+
4810 ; | Locate the P: handler and |
4820 ; | and copy the vectors to my|
4830 ; | handler. Copy information,|
4840 ; | addresses, and initialize |
4850 ; |    the PRINTER SPOOLER    |
4860 ; +---------------------------+
4870 ;
4880 START
4890     LDA HATABS+1 ;GET HANDLER ADDRESS
4900     LDX HATABS+2
4910     STA DEST    ;SAVE ADDRESS
4920     STX DEST+1
4930     STA OLDHAND ;KEEP A COPY FOR DOS CALL
4940     STX OLDHAND+1
4950 ;
4960     LDY #$00    ;MOVE HANDLER
4970 MOVELO
4980     LDA (DEST),Y ;GET HANDLER DATA
4990     STA OPEN,Y  ;SAVE IT
5000     INY 
5010     CPY #$06    ;SKIP PUT ADDRESS
5020     BNE MOVELO  ;YES
5030 ;
5040     LDY #$08    ;GET REST OF HANDLER
5050 MOVEHI
5060     LDA (DEST),Y ;GET SOME DATA
5070     STA OPEN,Y  ;SAVE IT
5080     INY 
5090     CPY #$0F    ;MOVE SOME MORE DATA?
5100     BNE MOVEHI  ;YEP, A FEW MORE BYTES
5110 ;
5120     LDA DOSINI  ;COPY DOSINI VECTOR
5130     LDX DOSINI+1
5140     STA RESET+1
5150     STX RESET+2
5160 ;
5170     LDA DOSVEC  ;COPY DOS VECTOR
5180     LDX DOSVEC+1
5190     STA CALLDOS+1
5200     STX CALLDOS+2
5210 ;
5220     LDA # <RESET ;TRAP RESET
5230     LDX # >RESET
5240     STA DOSINI
5250     STX DOSINI+1
5260 ;
5270     LDA MEMLO   ;SAVE OLD MEMLO VALUE
5280     LDX MEMLO+1
5290     STA OLDMEM
5300     STX OLDMEM+1
5310 ;
5320     LDA VVBLKD  ;SAVE OLD VVBLKD
5330     LDX VVBLKD+1
5340     STA OLDVVB
5350     STX OLDVVB+1
5360 ;
5370     JMP SETDOS  ;SETUP SPOOLER
5380 ;
5390 FINI
5400     BRK         ;FOR NO REASON
5410 ;
5420 ; ADD RUN ADDRESS FOR DOS
5430 ;
5440     *=  $02E0
5450     .WORD SMOVE
5460 ;
5470 ; END PROGRAM
5480 ;
5490     .END 


Back to previous page