
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