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 # BUFEND›1830 BNE EXITPUT ;NO›1840 ;›1850 LDA INPUT+1 ;MAYBE?›1860 CMP # 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 # 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›4220 STA DOSVEC ;MAKE SURE DOSVECTOR IS SET›4230 STX DOSVEC+1›4240 ;›4250 LDA # 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›4340 STA MEMLO ;TELL THE COMPUTER›4350 STX MEMLO+1›4360 ;›4370 LDA # 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›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›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 ›