;TOP OF FILE ;************************************************************* ;************************************************************* ;* * ;* THE FOLLOWING CODE IS CONTAINED IN VISUAL PART * ;* NUMBER IC244-033, V1050 DBOOT FIRMWARE. * ;* * ;* RELEASE 1.1, MARCH 27, 1984 (03-27-84) * ;* * ;************************************************************* ;************************************************************* PAGE ;DISPBOOT.ASM BRUCE KOMUSIN APRIL 15, 1983, PM ; STUART SHERMAN AUGUST 5, 1983 ; SEPT 16, 1983 ; I. NASSI/S.S. SEPT 21, 1983 ; S.S. DEC 06, 1983 ; FEB 02, 1984 ;************************************************************* ;************************************************************* ;02/02/84 ; PHOSPHOR SAVER NOW 'TELLS' Z-80 WHEN SCREEN BLANKS. ;************************************************************* ;12/06/83 ; FIXED INITIAL FORM FEED AND 'ESC c' PROBLEMS. ;************************************************************* ;11/07/83 ; DELETED FORM FEED AT 'START'. ;************************************************************* ;11/01/83 ; ADDED KEITH DAVISON'S ESCAPE SEQUENCES. ;************************************************************* ;10/25/83 ; DISABLE EXTERNAL INTERRUPTS FIRST THING DONE. ;************************************************************* ;10/21/83 ; MOVED 6845 INITIALIZATION TO START OF CODE TO FIX DRAM ; REFRESH PROBLEM. ;************************************************************* ;10/13/83 ; SPACE PROBLEMS -- SO MOVED 'HASH' & 'RAMTEST' TO ; CHARACTER FONT AREA ('GARBAGE' AREA). ALSO ; SUBROUTINIZED INITIALIZATION SECTION. ;************************************************************* ;10/12/83 ; CHANGED SCREEN DEFAULT TO DIM, ATTRIBUTE BOLD. ; ALSO ADDED 'HASH' & 'RAMTEST' ROUTINES. ;************************************************************* ;10/3/83 ; INVERT HARDWARE INTENSITY CONTROL BIT ;************************************************************* ;09/21/83 ; MORE CHANGES TO CORRECT MISTAKES. ;************************************************************* ;09/15/83 ; VERSION REQUEST ROUTINE FIXED & WORKS. ;************************************************************* ;09/07/83 ; FIXED 'ESC [ 2 J' ROUTINE. ;************************************************************* ;09/06/83 ; ADDED CODE FOR 'ESC [ 2 J' TO CLEAR SCREEN AND LEAVE ; CURSOR WHERE IT CURRENTLY IS. ;************************************************************* ;08/29/83 ; ADDED CODE FOR SOFTWARE CONTROLLED BLINK . ;************************************************************* ;08/22/83 ; ADDED ADJUSTABLE SCROLLING REGION A LA VT100. ;************************************************************* ;08/19/83 ; CHANGED 'BPL' TO 'BNE' TO LOAD 256 CHARACTERS INTO ; CHARACTER RAM INSTEAD OF 128 CHARACTERS. ;************************************************************* ;08/18/83 ; TWEEKED START OF (VERTICAL SYNC-1) FOR 16 MHZ 1050 ; BREADBOARD. ;************************************************************* ;08/12/83 ; FIXED DEFAULT G1 CHARACTER SET AND ADDED GRAPHICS ; CHARACTERS AT 020H THRU 03FH (G2 FONT). ;************************************************************* ;************************************************************* ;BOOTSTRAP PROGRAM FOR DISPLAY SECTION OF VISUAL "SOLUTION" ;6502 PROCESSOR MNEMONICS ;EQUATES ONTIME EQU 30 ;VALUE FOR 1/2 SECOND ON TIME OFFTIME EQU 30 ;VALUE FOR 1/2 SECOND OFF TIME VERSION EQU 3131H ;BUG FIX/MAJOR REV ie. BUG FIX 1 FOR REV 1 (RELEASE 1.1) ;MEMORY MAPPED I/O REGISTERS CRTCA EQU 08000H ;CRTC ADDRESS REGISTER CRTCD EQU 08001H ;CRTC DATA REGISTER IOPA EQU 09000H ;DISPLAY/PROCESSING I/O PORT A IOPB EQU 09001H ;DISPLAY/PROCESSING I/O PORT B IOPC EQU 09002H ;DISPLAY/PROCESSING I/O PORT C IOCTRL EQU 09003H ;DISPLAY/PROCESSING I/O CONTROL PORT ATT EQU 0A000H ;ATTRIBUTE REGISTER Z80 EQU 0B000H ;WRITE 01H TO HERE SETS Z-80 INTERRUPT RTC EQU 0C000H ;WRITE TO HERE RESETS VERTICAL RETRACE INTERRUPT ;ASCII CHARACTERS CR EQU 0DH LF EQU 0AH BS EQU 08H HT EQU 09H FF EQU 0CH SO EQU 0EH SI EQU 0FH NUL EQU 00H ESC EQU 1BH BEL EQU 07H SPC EQU 20H ;PROM ADDRESSES PROM EQU 0E000H ;START OF PROM PROMLEN EQU 8*1024 ;2764 PROM, 8K LONG ;NOTE; ;A USER PROGRAM MAY BE LOADED INTO THE RAM IN THE ADDRESS RANGE FROM ;0E00H TO 1FF9H. LOADING IS DONE BY MULTIPLE "MEMORY POKE" COMMANDS. ;AT LOCATIONS 1FF7H TO 1FF9H MUST BE A JUMP TO THE START OF THE ;ROUTINE TO BE EXECUTED WHEN ESC : IS RECEIVED. THE USER PROGRAM MAY ;USE ANY OF THE SUBROUTINES POINTED TO BY THE SUBROUTINE TABLE STARTING ;AT ADDRESS E002H IN PROM. ;THE USER PROGRAM MUST TERMINATE WITH AN RTS INSTRUCTION. PAGE ;DATA AREAS ;LOCATIONS 0-31 ARE GENERAL REGISTERS ORG 20H ;POINTERS TO THE RASTER LINES OF THE CHARACTER AT THE CURSOR POS'N. ;THESE POINTERS ARE UNDEFINED UNLESS THE LNOK VARIABLE IS NON-ZERO. LNOK: DS 1 ;LN0 - LN11 POINTERS DEFINED ONLY IF NON-ZERO LN0 DS 2 LN1 DS 2 LN2 DS 2 LN3 DS 2 LN4 DS 2 LN5 DS 2 LN6 DS 2 LN7 DS 2 LN8 DS 2 LN9 DS 2 LN10 DS 2 LN11 DS 2 CURMSK DS 12 ;12 BYTES OF THE CURSOR MASK. EXCLUSIVE-ORED WITH THE ; CURRENT CHARACTER TO EFFECT CURSOR DISPLAY. REVMSK DS 12 ;12 BYTES OF 0FFH. EXCLUSIVE-ORED WITH THE CURRENT ; CHARACTER TO EFFECT CHARACTER REVERSAL. ;CHARACTER ORIENTED VARIABLES CONDS DS 1 ;CONDITIONS. BITS: ; 7 1 = OVERSTRIKE, 0 = REPLACE ; 6 1 = CURSOR WANTED FOR DISPLAY ; 5 1 = CURSOR BLINK ; 4 1 = SLOW SCROLL ; 3 1 = AUTO NEWLINE ; 2 1 = DISABLE PHOSPHOR SAVER ; 1 1 = UNDERLINE ENABLE HCUR DS 1 ;CURRENT HORIZONTAL CURSOR POSITION, 0 - 79 VCUR DS 1 ;CURRENT VERTICAL CURSOR POSITION, 0 - 24 ATTRIB DS 1 ;CURRENT ATTRIBUTES BYTE. BITS: ; 7 SOFTWARE BLINK BIT ; 6 1 = INTENSITY ATTRIBUTE MAKES TEXT BRIGHTER ; 0 = INTENSITY ATTRIBUTE MAKES TEXT DIMMER ; 5 HARDWARE BLANK THE WHOLE SCREEN ; 4 HARDWARE REVERSE THE WHOLE SCREEN ; 3 SOFTWARE REVERSE TO BE DONE DURING WRITING ; 2 1 = SET ATTRIBUTE RAM FROM ATTRIB LATCH ; 0 = PERSERVE LAST READ ATTRIBUTE ; 1 BLINK TO BE DONE DURING WRITING ; 0 INTENSITY TO BE DONE DURING WRITING ;NOTE: THIS BYTE DOUBLES AS THE RAM "SHADOW" OF THE ; ATTRIBUTE LATCH AT ADDR A000H CRTCRG12 DS 1 ;"SHADOW" OF CRTC HOME ADDRESS HIGH REGISTER CRTCRG13 DS 1 ;"SHADOW" OF CRTC HOME ADDRESS LOW REGISTER CURDSP DS 1 ;SOFTWARE CURSOR CURRENTLY BEING DISPLAYED: NON-ZERO CURBLK DS 3 ;CURSOR BLINK AND PHOSPHOR SAVER COUNTER PSAVCNT DS 1 ;PHOSPHOR SAVER 4-MINUTE COUNTER SOFLG DS 1 ;SHIFT OUT FLAG. 0=NORMAL(SHIFT IN), 80H=SHIFT OUT MODE G0VAL DS 1 ;VALUE ADDED TO 7-BIT CHAR CODE TO ADDRESS CHARACTER ; GENERATOR FOR G0 GRAPHICS SET G1VAL DS 1 ;VALUE ADDED TO 7-BIT CHAR CODE TO ADDRESS CHARACTER ; GENERATOR FOR G1 GRAPHICS SET CSIPTR DS 1 ;POINTER TO CURRENT PARAMETER DURING CSI STRING CSIPR0 DS 2 ;CSI PARAMETER 0 CSIPR1 DS 2 ;CSI PARAMETER 1 CSIPR2 DS 2 ;CSI PARAMETER 2 CSIPR3 DS 2 ;CSI PARAMETER 3 CSIPR4 DS 2 ;CSI PARAMETER 4 CSIPR5 DS 2 ;CSI PARAMETER 5 CSIPR6 DS 2 ;CSI PARAMETER 6 CSIPR7 DS 2 ;CSI PARAMETER 7 CSIPR8 DS 2 ;CSI PARAMETER 8 CSIPR9 DS 2 ;CSI PARAMETER 9 CSIPRX DS 2 ;FAKE PARAMETER NECESSARY TO GRACEFULLY TRICK CSI CODE ; IF TOO MANY PARAMETERS SENT PAGE ;GRAPHICS ORIENTED VARIABLES ;POINT ROUTINE VARIABLES. X DS 2 ; 0 <= X <= 639 Y DS 2 ; 0 <= Y <= 299 XYDOTS DS 1 ;ORIGINAL BIT MASK FOR CONTROLLING DOTTED, DASHED. TMPXYDOT DS 1 ;BIT MASK ROTATED AND USED TO CONTROL DOTTED, DASHED. XYOPR DS 1 ;BIT OPERATION. 0 = SET, + = RESET, - = TOGGLE BIT XYOK DS 1 ;NON-ZERO IF THE XYADDR AND XYMASK VARIABLES OK XYADDR DS 2 ;PTR TO THE BYTE ADDRESS CONTAINING X,Y XYMASK DS 1 ;BIT MASK FOR POINT X,Y ;LINE DRAWING VARIABLES. X1 DS 2 ;SECOND COORDINATE Y1 DS 2 XSTEP DS 1 ;STEPS ARE: + = INCREMENT, - = DECREMENT, 0 = NO CHANGE YSTEP DS 1 XDELTA DS 2 ;DELTAS ARE ABSOLUTE DIFFERENCE OF COORDINATE 1 AND 0 YDELTA DS 2 VARS DS 2 ;VARS USED TO DECIDE IF DEPENDANT VARIABLE NEEDS STEP ;CIRCLE DRAWING VARIABLES. XC DS 2 ;CENTER OF CIRCLE, X YC DS 2 ;CENTER OF CIRCLE, Y Z EQU VARS ;(B*B)*(X*X) + (A*A)*(Y*Y) - (A*A)*(B*B)*(R*R) ; I.E. DIFFERENCE BETWEEN MATHEMATICALLY CORRECT ; CIRCLE AND THE CURRENT POINT JUST PLOTTED DZX DS 2 ;CHANGE IN Z FOR STEP OF +-1 IN X DZY DS 2 ;CHANGE IN Z FOR STEP OF +-1 IN Y DDZX DS 2 ;CHANGE IN DZX OR DZTX FOR STEP OF +-1 IN X DDZY DS 2 ;CHANGE IN DZY OR DZTY FOR STEP OF +-1 IN Y DZTX DS 2 ;CHANGE IN Z FOR STEP OF +-1/2 IN X DZTY DS 2 ;CHANGE IN Z FOR STEP OF +-1/2 IN Y BSQ: DS 2 ;THE PIXEL ASPECT RATIO FOR X (SQUARED) ASQ: DS 2 ;THE PIXEL ASPECT RATIO FOR Y (SQUARED) QUAD: DS 1 ;CURRENT QUADRANT ENDQUAD:DS 1 ;END POINT QUADRANT PAGE ;NEW VARIABLES ADDED FOR VERSION 2, VISUAL "SOLUTION". CLKTICK DS 1 ;INCREMENTED BY 1 EACH CLOCK TICK (EACH SCREEN SCAN) LOGTOP DS 1 ;LOGICAL TOP LINE OF SCREEN, DEFAULTED TO 0 (TOP LINE ;OF SCREEN.) THIS VALUE IS USED FOR ADJUSTABLE SCROL- ;LING REGIONS TO BE USED BY DELETE LINE ROUTINE. LOGBOT DS 1 ;LOGICAL BOTTOM LINE OF SCREEN, DEFAULTED TO 24 (FULL ;25-LINE SCREEN.) THIS VALUE IS USED TO TERMINATE THE ;INSERT LINE AND DELETE LINE ROUTINES. KBDBYT DS 1 ;"SHADOW" OF THE BYTE TO BE SENT TO THE VISUAL KB010 ;KEYBOARD WHEN THE KEYBOARD MODE IS TO BE CHANGED. ;THE BITS IN THIS BYTE ARE ASSUMED TO BE AS FOLLOWS: ; 7 BELL (250 MILLISEC OF 1 KHZ TONE) ; 6 KEYCLICK ENABLE ; 5 HELP KEY (FUNCTION KEY) LED, KEY 79 ; 4 CAPS LOCK LED, KEY 53 ; 3 AUTO-REPEAT ENABLE ; 2 RESERVED FOR FUTURE USE ; 1-0 ENCODING SELECTION ; 00 US/UK ; 01 AZERTY ; 10 NOR/DAN/SWE/FINN ; 11 PORT/SPANISH BLNKCTR DS 1 ;BLINK COUNTER FOR SOFTWARE BLINK TIMEON DS 1 ;TO ENABLE ON THE FLY CHANGES TO BLINK 'ON TIME' TIMEOFF DS 1 ;TO ENABLE ON THE FLY CHANGES TO BLINK 'OFF TIME' SCRATCH DS 1 ;SCRATCH VARIABLE PAGE ;CHARACTER FONT TABLE. ORG 0200H ;THE CHARACTER FONTS ARE READ FROM THE PROM, BIT ORDER REVERSED, AND ; WRITTEN TO THIS RAM FOR USE BY THE DISP ROUTINE. THIS ALLOWS THE ; CHARACTERS TO BE INDIVIDUALLY RE-DEFINED IF NECESSARY. ;CHARACTERS IN THE FONT TABLE ARE ARRANGED DIFFERENTLY THAN IN THE ; PROM; IN PROM EACH SUCCESSIVE BYTE OF A GIVEN CHARACTER IS ADJACENT ; IN MEMORY. IN THIS TABLE, HOWEVER, ALL TOP BYTES ARE IN SUCCESIVE ; LOCATIONS, THEN ALL SECOND BYTES, ALL THIRD, ETC. OBVIOUSLY, BOTH ; FORMATS REQUIRE THE SAME AMOUNT OF ROOM. THIS ARRANGEMENT IN RAM ; IS CHOSEN BECAUSE IT ALLOWS QUICKER ACCESS TO THE BYTES OF A GIVEN ; CHARACTER. ;TABLE MUST BEGIN AT 0200H; SEE POKE AND PEEK FONT CODE. CGLN0 DS 256 CGLN1 DS 256 CGLN2 DS 256 CGLN3 DS 256 CGLN4 DS 256 CGLN5 DS 256 CGLN6 DS 256 CGLN7 DS 256 CGLN8 DS 256 CGLN9 DS 256 CGLN10 DS 256 CGLN11 DS 256 CGEND: PAGE ;USER AREA ORG 2000H-(3*3) XUSER DS 3 NMI DS 3 XINT DS 3 PAGE ;CODE AREA ORG PROM ; P R O M V E R S I O N DW VERSION ;CURRENT VERSION OF PROGRAM ; A D D R E S S T A B L E F O R S U B R O U T I N E S DW MAIN DW DOIT DW DISP DW GETCHR DW PUTCHR DW XCONTROL DW GETPARS DW DOLN DW NEWGCUR DW DOGLN DW DOXSTEP DW DOYSTEP DW POINT DW PNT DW XPLUSY DW XMINUSY DW MOV2W DW MOV1W DW XMULT DW XNEG DW IPUTCHR PAGE ; M A I N L O O P DOIT: ;UNSTRUCTERED JUMP OUT OF A LOWER LEVEL ROUTINE BECAUSE OF AN ILLEGAL ; CHARACTER ENCOUNTERED IN AN ESCAPE SEQUENCE. EXIT THE SEQUENCE AND ; DO WHATEVER THE CHARACTER WOULD HAVE DONE IN THE NORMAL STATE. LDX #0FFH TXS ;RESET THE STACK BNE DOIT1 ;EXECUTE THE CHARACTER (ALWAYS BRANCHES) WRITE: JSR DISP ;WRITE THE CHARACTER IN THE ACC TO THE SCREEN MAIN: SEI ;DISABLE INTERRUPTS LDA ATTRIB ;GET ATTRIBUTE BYTE AND #0FBH ;RESET BIT 2 TO ZERO (STREAMING BIT - PRESERVE READ ATTRIBUTE) STA ATTRIB ;RESTORE ATTRIB BYTE STA ATT ;TELL HARDWARE CLI ;RE-ENABLE INTERRUPTS JSR GETCHR ;ACC = THE NEXT CHARACTER FROM THE PROCESSING SECTION DOIT1: BIT CTRLTST ;TEST CHARACTER AGAINST CONTROL CHARACTER MASK OF 60H BNE WRITE ;NOT A CONTROL CHARACTER, DISPLAY IT JSR XCONTROL ;THE CHARACTER HAS SPECIAL MEANING & MUST BE EXECUTED JMP MAIN ;REPEAT FOREVER PAGE ;EXECUTE THE APPROPRIATE CONTROL FUNCTION ;CONTROL CHARACTER IN ACC, SEE IF IT IS ONE OF THE ACTIVE ONES. XCONTROL:CMP #LF ;LINE FEED? (TEST FIRST FOR THE SLOWEST FREQUENTLY ; RECEIVED CHARACTER) BEQ XLF CMP #CR ;CARRIAGE RETURN? (MOST COMMONLY RECEIVED CHAR) BEQ XCR CMP #HT ;TAB? BEQ XHT CMP #FF ;FORM FEED? (ABSOLUTELY SLOWEST CHAR NEXT) BEQ XFF CMP #BS ;BACKSPACE? BEQ XBS CMP #9BH ;8-BIT CONTROL SEQUENCE INTRODUCER? BEQ GOXCSI1 CMP #SO ;SHIFT OUT (TO ALTERNATE 128-CHARACTER SET)? BEQ XSO CMP #SI ;SHIFT IN (TO NORMAL ASCII 128-CHARACTER SET)? BEQ XSI CMP #BEL ;BELL? BEQ XBEL CMP #ESC ;ESCAPE? BNE RTS0 ;IF NONE OF THE ABOVE, IGNORE IT JMP XESC GOXCSI1:JMP XCSI ;EXECUTE COMMAND SEQUENCE INTRODUCER CODE XHT: ;HORIZONTAL TAB RECEIVED, PROCESS IT. LDA #SPC JSR DISP ;UNCONDITIONALLY OUTPUT AT LEAST ONE SPACE LDA HCUR CMP #79 ;ON LAST POSITION OF THE LINE? BNE XHT1 ;NO, OUTPUT MORE SPACES UNTIL HCUR IS MULTIPLE OF 8 LDA CONDS ;YES, SEE IF WE SHOULD FALL OFF THE LINE ONTO THE NEXT AND #08H ;AUTO NEWLINE ON? BNE XHT ;YES, OUTPUT ONE MORE SPACE SO WE GO TO POS'N 00 OF ; THE NEXT LINE RTS ;NO, STOP XHT1: AND #07H ;ARE WE AT A POSITION WHICH IS MULTIPLE OF EIGHT? BNE XHT ;NO, OUTPUT MORE SPACES RTS ;YES, DONE XBEL: ;BELL RECEIVED, INTERRUPT THE Z-80 TO TELL IT TO BEEP. LDA KBDBYT ORA #80H ;TURN ON BELL BIT IN Z-80'S KEYBOARD BYTE JMP IPUTCHR ;INTERRUPT Z-80 AND SEND THIS BYTE PAGE ;SHIFT OUT RECEIVED, PROCESS IT. XSO: LDA #80H STA SOFLG ;SET SHIFT OUT FLAG TO 80H SO THE G1 FONT IS USED RTS0: RTS ;SHIFT IN RECEIVED, PROCESS IT. XSI: LDA #0 STA SOFLG ;CLEAR SHIFT OUT FLAG TO 00H SO THE G0 FONT IS USED RTS ;BACKSPACE RECEIVED, PROCESS IT. XBS: DEC HCUR ;MOVE THE CURSOR BACKWARDS BPL LNSNG ;IF NOT BEFORE THE BEGINNING, INDICATE LN NOT OK, DONE LDA #79 STA HCUR ;MOVE CURSOR TO THE END OF THE LINE XUP: DEC VCUR ;MOVE CURSOR TO THE PREVIOUS LINE BPL LNSNG ;IF NOT BEFORE FIRST LINE, INDICATE LN NOT OK, DONE LDA #24 STA VCUR ;MOVE CURSOR TO THE LAST LINE BNE LNSNG ;INDICATE LN NOT OK, DONE (ALWAYS BRANCHES) ;CARRIAGE RETURN RECEIVED, PROCESS IT. XCR: LDA #0 STA HCUR ;MOVE THE CURSOR TO THE BEGINNING OF THE LINE LNSNG: LDA #0 STA LNOK ;FORCE RE-COMPUTATION OF LN0 - LN11 POINTERS RTS ;LINE FEED RECEIVED, PROCESS IT. XLF: LDA VCUR ;CURSOR ON LAST LINE? (SCROLLING NECESSARY?) CMP LOGBOT ;COMPARE WITH LOGICAL BOTTOM OF SCREEN BEQ SCROL ;YES, DO THE SCROLL INC VCUR BNE LNSNG ;INDICATE LN NOT OK, DONE (ALWAYS BRANCHES) ;FORM FEED RECEIVED, PROCESS IT. XFF: ;THIS MEANS TO CLEAR ALL BYTES TO 00 FROM ADDRESS 2000H TO 7FFFH, ; INCLUDING THE ATTRIBUTE BYTES. ;TURN OFF ALL ATTRIBUTES. LDA CONDS ;GET CONDITION BYTE AND #0FDH ;TURN OFF UNDERLINE STA CONDS ;RESTORE CONDITION BYTE SEI ;DISABLE INTERRUPTS LDA ATTRIB ;ACC = THE ATTRIBUTES AND #70H ;TURN OFF ALL ATTRIBUTES EXCEPT OVERALL BRIGHTNESS ORA #04H ;SET BIT 2 TO A ONE (ENABLE ATTRIBUTE WRITE FROM LATCH) STA ATTRIB ;TELL THE SOFTWARE STA ATT ;TELL THE HARDWARE CLI ;RE-ENABLE INTERRUPTS ;FORM A TABLE IN MEMORY. LDY #0 LDA #80H LDX #11 XFF1: SEC SBC #10H STA 0,X DEX STY 0,X DEX BPL XFF1 ;AT ADDR 10 PTR TO 7000H ;AT ADDR 8 PTR TO 6000H ;AT ADDR 6 PTR TO 5000H ;AT ADDR 4 PTR TO 4000H ;AT ADDR 2 PTR TO 3000H ;AT ADDR 0 PTR TO 2000H TAX ;X = 20H TYA ;ACC = 00 ;NOW DO THE CLEARING IN A PARTIALLY "UN-ROLLED" LOOP. CLRLUP: STA (0),Y STA (2),Y STA (4),Y STA (6),Y STA (8),Y STA (10),Y ;CLEAR ALL THE BYTES THAT WE CAN ADDRESS WITH THE ; Y REGISTER FROM 00 TO FF INY BNE CLRLUP ;DO 256 CLEARS ;NOW INCREMENT THE PAGES TO GET THE OTHER ADDRESSES. INC 1 INC 3 INC 5 INC 7 INC 9 INC 11 BPL CLRLUP ;CONTINUE IF THE 7X00H PART HASN'T INCREMENTED TO 8000H ;CLEARING DONE. NOW SET UP THE SOFTWARE VARIABLES. STA HCUR STA VCUR ;CURSOR TO HOME POSITION STA LNOK ;FORCE RE-COMPUTATION OF LN0 - LN11 POINTERS STA XYOK ;SAME FOR GRAPHIC VARIABLES: THIS FIXES OUTSTANDING BUG ;POINT THE HARDWARE START OF SCREEN ADDRESS TO 2000H. ;X = 20H FROM ABOVE SEI ;DISABLE INTERRUPTS STX CRTCRG12 ;SET SOFTWARE TO 2000H, THE START OF THE SCREEN BUFFER STA CRTCRG13 CLI ;RE-ENABLE INTERRUPTS RTS ;RETURN FROM SUBROUTINE PAGE SCROL: ;FIRST CHECK FOR ALTERNATE SCROLLING REGION LDA LOGTOP ;GET LOGICAL TOP LINE BNE ALTSCROL ;OTHER THAN TOP LINE ? IF YES, BRANCH LDA #24 ;LOAD ACC W/ BOTTOM LINE NUMBER CMP LOGBOT ;OTHER THAN BOTTOM LINE ? BNE ALTSCROL ;YES, DO SELECTIVE SCROLL ; ;CLEAR THE SUB-CELL JUST BELOW THE BOTTOM OF THE SCREEN AND THEN ; SCROLL IT UP ONTO THE SCREEN. DO THIS FOUR TIMES FOR THE FULL ; CHARACTER LINE. ;FIRST, SET UP THE MAJOR LOOP COUNTER TO CLEAR AND SCROLL 4 SUB-CELLS. LDA #3 STA 6 ;LOC 6 IS MAJOR LOOP COUNTER ;WE LOOP UNTIL NEGATIVE SCR1: ;WE COMPUTE "26-TH. LINE" BY ADDING 25 * (4 * 80) = 1F40H TO THE HOME ; ADDRESS FROM THE CRTC. LDA CRTCRG13 ;ACC = HOME ADDR LOW CLC ADC #40H ;ADD 1F40H LOW TAY ;Y = 26-TH LINE LOW LDA CRTCRG12 ;ACC = HOME ADDR HIGH ADC #1FH ;ADD 1F40H HIGH PLUS THE CARRY AND #1FH ORA #20H ;WRAP AROUND FROM 3FFFH TO 2000H ;ACC,Y = PTR TO NEXT SUB-CELL AFTER THE BOTTOM OF SCREEN. LDX #80 ;CLEAR 80 SUB-CELLS JSR CLRSUB ;NOW ACTUALLY MOVE THE SOFTWARE HOME ADDRESS DOWNWARDS BY ONE ; SUB-CELL, EITHER SLOWLY OR IMMEDIATELY. LDA CRTCRG13 ;ACC = HOME ADDRESS LOW CLC ADC #80 PHA ;SAVE VALUE ON STACK LDA CRTCRG12 ;ACC = CRTC HOME ADDRESS HIGH ADC #0 ;ADD IN CARRY, IF ANY AND #1FH ORA #20H ;WRAP AROUND 3FFFH TO 2000H SEI ;DISABLE INTERRUPTS STA CRTCRG12 ;UPDATE HOME ADDRESS HIGH PLA ;GET SAVED VALUE STA CRTCRG13 ;SEND TO 6845 CTRC CHIP CLI ;RE-ENABLE INTERRUPTS LDA 6 ;ACC = CURRENT LOOP COUNT BEQ SCR3 ;ON THE LAST TIME THROUGH THE LOOP, ALWAYS COPY THE ; SOFTWARE SCREEN ADDRESS TO THE HARDWARE ;ON THE THREE OTHER TIMES, COPY ONLY IF WE'RE DOING A SLOW SCROLL. LDA CONDS ;GET THE CONDITIONS AND #10H ;TEST THE SLOW SCROLL BIT BEQ NOSLOW ;IF LOW, NO SLOW SCROLL ;DELAY FOR SOME TIME SO THE FOUR INDIVIDUAL SUB-CELL SCROLLS ARE SEEN. SCR3: LDX #11 ;WAIT ABOUT 18.2 MILLISECONDS STX 7 ;TEMP STORAGE TO HOLD DELAY COUNT SCR2: DEC 7 ;DECREMENT COUNT BNE SCR2 ;INNER DELAY IS 8 CYCLES, 7.11 USECS PER LOOP DEX ;DECREMENT X REGISTER BNE SCR2 ;OUTER DELAY IS 1.82 MILLISECONDS PER LOOP NOSLOW: DEC 6 ;DONE ALL FOUR SCROLLS? BPL SCR1 ;NO, CONTINUE JSR LNSNG ;INDICATE LN NOT OK JMP XYNG ;SAME FOR XY ALTSCROL: LDA VCUR ;GET CURRENT VERTICAL CURSOR POSITION PHA ;SAVE ON STACK LDA LOGTOP ;GET CURRENT LOGICAL TOP LINE STA VCUR ;...& PUT INTO CURRENT VERTICAL CURSOR POSITION JSR XDL ;DELETE A LINE AT LOGTOP PLA ;RESTORE SAVED CURRENT VERTICAL POSITION STA VCUR ;... RTS ;RETURN FROM SUBROUTINE PAGE GOXPOKE:JMP XPOKE GOXPEEK:JMP XPEEK GOXCSI2:JMP XCSI GOSTART:JMP START GOXGRPH:JMP XGRPH GOXUSER:JMP XUSER ;ESCAPE RECEIVED, EXAMINE THE NEXT CHARACTER(S) FOR FURTHER INFO. XESC: JSR GETCHR ;ACC = THE NEXT CHARACTER CMP #"[" ;ESC FOLLOWED BY [ IS COMMAND STRING INTRODUCER BEQ GOXCSI2 CMP #"<" ;ESC FOLLOWED BY < IS A PEEK COMMAND BEQ GOXPEEK CMP #"c" ;ESC FOLLOWED BY LOWER CASE C IS A RESET COMMAND BEQ GOSTART CMP #"=" ;ESC FOLLOWED BY = IS A NON-PREFERRED CURSOR POS'N BEQ XCUR CMP #"(" ;ESC FOLLOWED BY ( IS A SET G0 FONT COMMAND BEQ XSETG0 CMP #")" ;ESC FOLLOWED BY ) IS A SET G1 FONT COMMAND BEQ XSETG1 CMP #">" ;ESC FOLLOWED BY > IS A POKE COMMAND BEQ GOXPOKE CMP #";" ;ESC FOLLOWED BY ; IS A MISCELLANEOUS COMMAND BEQ XMISC CMP #"?" ;ESC FOLLOWED BY ? IS A GRAPHICS COMMAND BEQ GOXGRPH CMP #":" ;ESC FOLLOWED BY : IS USER COMMAND BEQ GOXUSER JMP DOIT ;IF NO MATCH FOUND, EXIT ESCAPE MODE AND PROCESS ; CHARACTER NORMALLY ;NON-PREFERRED CURSOR POSITION COMMAND. ;ESC = RECEIVED, WAIT FOR CURSOR POS'N IN THE FORM Y+1FH X+1FH ; (X AND Y IN THE RANGE 1 TO 80 AND 1 TO 25) XCUR: JSR GETCHR ;READ Y+1FH SEC SBC #20H ;STRIP THE OFFSET PHA ;SAVE Y COORDINATE IN RANGE 0 - 24 JSR GETCHR ;READ X+1FH SEC SBC #20H ;STRIP THE OFFSET TAX ;X = X COORDINATE IN RANGE 0 - 79 PLA TAY ;Y = Y COORDINATE JMP TSTCUR ;SEE IF LEGAL COORDS XSETG0: ;SET UP THE G0 CHARACTER FONT. JSR GETCHR ;ACC = THE FONT CHOSEN LDX #G0VAL ;RESULT WILL BE WRITTEN TO G0 VALUE SETGX: LDY #(-20H) ;SUBTRACT 20H FROM NORMAL ASCII FOR FIRST 96 CHARS CMP #"0" ;SELECTOR OF 0? BEQ SETGX1 ;YES, SET IT LDY #40H ;ADD 40H TO NORMAL ASCII FOR SECOND 96 CHARS CMP #"1" ;SELECTOR OF 1? BEQ SETGX1 ;YES, SET IT LDY #0A0H ;ADD 0A0H TO NORMAL ASCII FOR THIRD 64 CHARS CMP #"2" ;SELECTOR OF 2? BNE RTS1 ;NO, IGNORE COMMAND SETGX1: STY 0,X ;SET GXVAL TO THE PROPER NUMBER RTS1: RTS XSETG1: ;SET UP THE G1 CHARACTER FONT. JSR GETCHR ;ACC = THE FONT CHOSEN LDX #G1VAL ;RESULT WILL BE WRITTEN TO G1 VALUE BNE SETGX ;CONTINUE (ALWAYS BRANCHES) XMISC: ;MISCELLANEOUS COMMANDS EITHER SET THE OVERALL SCREEN BRIGHTNESS OR ; SET OR CLEAR TERMINAL MODES, I.E. BITS IN THE CONDS VARIABLE. JSR GETCHR ;ACC = THE PARAMETER CMP #40H ;LESS THAN 40H? BCC RTS1 ;YES, LEVEL SET, IGNORE IT IN THIS VERSION LDX #40H ;DEAL WITH INTENSITY BIT IN ATTRIBUTE BYTE CMP #"P" ;INTENSITY ATTRIBUTE IS DIM? BNE XM1 XM2: TXA ;ACC = THE BIT TO TURN ON SEI ;DISABLE INTERRUPTS ORA ATTRIB ;TURN IT ON XM3: STA ATTRIB ;SAVE FOR SOFTWARE STA ATT ;INFORM HARDWARE CLI ;RE-ENABLE INTERRUPTS RTS XM1: CMP #"X" ;INTENSITY ATTRIBUTE IS BOLD? BNE XM4 XM5: TXA ;ACC = THE BIT TO TURN OFF EOR #0FFH ;ACC = ALL BITS ON BUT THE ONE TO TURN OFF SEI ;DISABLE INTERRUPTS AND ATTRIB ;TURN IT OFF JMP XM3 XM4: LDX #10H ;DEAL WITH REVERSE SCREEN BIT CMP #"Y" ;REVERSE SCREEN? BEQ XM2 CMP #"Q" ;NORMAL SCREEN? BEQ XM5 CMP #"\" ;SET LOGICAL LAST LINE? BNE XM65 LDA VCUR ;ACC = CURRENT LINE NUMBER STA LOGBOT ;SAVE IT RTS XM65: CMP #"t" ;SET LOGICAL TOP LINE ? BNE XM6 ;NO, CHECK NEXT SEQUENCE LDA VCUR ;ACC = CURRENT LINE NUMBER STA LOGTOP ;SAVE IT RTS ;RETURN FROM SUBROUTINE XM6: LDX #40H ;DEAL WITH CLICK ENABLE/DISABLE IN KEYBOARD BYTE CMP #"Z" ;ENABLE CLICK? BNE XM7 XM8: TXA ;ACC = BIT TO TURN ON ORA KBDBYT XM9: STA KBDBYT JMP IPUTCHR ;INTERRUPT Z-80 AND SEND THE NEW KEYBOARD BYTE XM7: CMP #"R" ;DISABLE CLICK? BNE XM10 XM11: TXA EOR #0FFH ;ACC = ALL BITS ON BUT THE ONE TO TURN OFF AND KBDBYT ;TURN IT OFF JMP XM9 XM10: LDX #08H ;DEAL WITH AUTO-REPEAT BIT CMP #"[" ;ENABLE AUTO-REPEAT? BEQ XM8 CMP #"S" ;DISABLE AUTO-REPEAT? BEQ XM11 LDX #0 ;DEAL WITH THE MAPPING OPTIONS CMP #"U" ;US/UK? BEQ XM12 INX CMP #"]" ;AZERTY? BEQ XM12 INX CMP #"V" ;NOR/DAN/SWE/FINN? BEQ XM12 INX CMP #"^" ;PORT/SPANISH? BNE XM13 XM12: LDA KBDBYT AND #0FCH ;STRIP OFF CURRENT MAPPING BITS STA KBDBYT JMP XM8 XM13: CMP #"T" ;TRANSPARENT MODE? BNE CHECKV ;NO, VERSION NUMBER REQUEST ? ;TRANSPARENT MODE. DISPLAY ALL RECEIVED CHARACTERS. JSR XFF ;CLEAR THE SCREEN. TURN OFF ALL THE ATTRIBUTES. JSR XSI ;ENTER NORMAL MODE TRNS1: JSR GETCHR ;GET THE NEXT CHARACTER TRNS2: PHA ;SAVE IT LDX #0 ;X = THE REVERSE AND BRIGHT ATTRIBUTES, IF ANY ; (WRITE CHARACTERS WITH BIT 7 ON AS REVERSED, AND ; CONTROL CHARACTERS AS BRIGHT.) TAY ;DOES THE CHARACTER HAVE BIT 7 ON? BPL TRNS3 ;NO, CONTINUE LDX #08H ;SET-UP TO WRITE CHARACTER REVERSED AND #7FH ;STRIP THE CHARACTER'S BIT 7 TRNS3: BIT CTRLTST ;IS THE CHARACTER A CONTROL CHARACTER? BNE TRNS4 ;NO, CONTINUE INX ;SET-UP TO WRITE THE CHARACTER BRIGHT CLC ADC #40H ;FORCE THE CONTROL CHARACTER TO ITS UPPER CASE EQUIV. TRNS4: TAY ;Y = THE CHARACTER TXA ;ACC = THE ATTRIBUTE TO USE FOR WRITING SEI ;DISABLE INTERRUPTS ORA ATTRIB STA ATTRIB ;SET THE ATTRIBUTES FOR THIS WRITE STA ATT ;SET HARDWARE ATTRIBUTES TOO CLI ;RE-ENABLE INTERRUPTS TYA ;ACC = THE CHARACTER AGAIN JSR DISP ;WRITE THE CHARACTER SEI ;DISABLE INTERRUPTS LDA ATTRIB AND #0F6H ;STRIP BOTH THE BRIGHT AND REVERSE ATTRIBUTES, IF SET STA ATTRIB STA ATT CLI ;RE-ENABLE INTERRUPTS PLA ;ACC = THE ORIGINAL CHARACTER CMP #ESC ;IS IT THE ESCAPE CHARACTER? BNE TRNS1 ;NO, CONTINUE JSR GETCHR ;WAIT FOR THE NEXT CHARACTER CMP #"c" ;IS THE FIRST ESCAPE FOLLOWED BY A LOWER CASE C? BNE TRNS2 ;NO, WRITE THIS FOLLOWING CHARACTER JMP START ;YES, DO THE RESET ;VERSION NUMBER REQUEST CHECKV: CMP #"v" ;VERSION NUMBER REQUEST ? BNE SETCLR ;SET/CLEAR TERMINAL MODE CHECK LDA # LOW VERSION ;GET MAJOR REV NUMBER JSR PUTCHR ;SEND 1-ST BYTE TO Z-80 uP LDA # HIGH VERSION ;GET MINOR REV NUMBER JSR PUTCHR ;SEND 2-ND BYTE TO Z-80 uP RTS ;RETURN FROM SUBROUTINE ;SET/CLEAR TERMINAL MODES. SETCLR: CMP #48H ;40H-47H IS FOR CLEAR, 48H-4FH IS FOR SET ;CARRY CLEAR IF FOR CLEAR AND #07H ;ISOLATE THE BIT NUMBER TO SET/CLEAR TAY ;Y = THE BIT NUMBER LDA BITPAT,Y ;ACC = THE BIT MASK FOR THE BIT NUMBER BCC CLRBT ;IF CARRY CLEAR, CLEAR THE BIT ORA CONDS ;SET THE BIT MSC1: STA CONDS ;UPDATE IT RTS CLRBT: EOR #0FFH ;INVERT THE BIT MASK AND CONDS ;CLEAR THE BIT JMP MSC1 ;CONTINUE XPOKE: JSR GETCHR ;GET NEXT CHARACTER CMP #":" ;DOWN LOAD HEX FILE ? BEQ GOHEX ;YES, SO GO DO IT CMP #">" ;ONE OF THE SOFT CHARACTER COMMANDS ? BNE FIXPOKE ;NO, SO FIX UP POKE COMMAND LDY LNOK ;PER KEITH DAVISON BNE SKIPFIX ;PER KEITH DAVISON JSR DOLN1 ;PER KEITH DAVISON SKIPFIX: JSR GETCHR ;GET NEXT CHARACTER CMP #"1" ;LOAD ONE SOFT CHARACTER ? BEQ GOSOFT ;YES, SO GO DO IT CMP #"H" ;LOAD MULTIPLE SOFT CHARACTERS ? BEQ GOSOFTH ;YES, SO GO DO IT FIXPOKE: LDX #CSIPRX ;X = PTR TO LAST PARAMETER PHA ;SAVE LAST CHARACTER ON STACK LDA #0 ;ACC = 0 FIXPOKE1: DEX ;DECREMENT COUNT STA 0,X ;CLEAR THE PARAMETER CPX #CSIPR0 ;AER WE DONE ? BNE FIXPOKE1 ;NO, SO DO SOME MORE STX CSIPTR ;INITIALIZE PARA POINTER TO FIRST PARAMETER PLA ;RESTORE SAVED CHARACTER JSR PARLUP1 ;ENTER 'GETPARS' ROUTINE (GET CSI TYPE PARAMS) LDX #0 ;X = 00 CMP #"F" ;FONT POKE? BEQ POKFNT CMP #"M" ;MEMORY POKE? BNE RTS4 ;NO, IGNORE POKMEM: ;PARAMETER 0 IS ADDRESS, PARAMETER 1 IS DATA. LDA CSIPR1 ;ACC = DATA STA (CSIPR0,X) ;WRITE DATA TO MEMORY RTS4: RTS GOHEX: JMP HEX ;DOWN LOAD INTEL HEX FILE GOSOFT: JMP WRITE1 ;LOAD ONE SOFT CHARACTER GOSOFTH:JMP WRITEH ;LOAD MULTIPLE SOFT CHARACTERS POKFNT: ;PARAMETER 0 IS CHARACTER, PARAMETER 1 IS LINE, PARAMETER 2 IS DATA. LDA CSIPR0+1 ;IF CHAR > 255, THEN IT'S A CURSOR FONT BNE POKCUR LDY CSIPR1 ;Y = RASTER LINE INY INY ;Y = PAGE IN MEMORY FOR TABLE OF THOSE RASTER LINES STY CSIPR0+1 ;CSIPR0 = PTR TO PROPER BYTE IN CHARACTER GENERATOR POKF1: LDA CSIPR2 ;ACC = DATA STA (CSIPR0,X) ;WRITE DATA TO FONT RTS POKCUR: LDA CSIPR1 ;ACC = RASTER LINE CLC ADC #CURMSK ;ACC = OFFSET IN CURSOR MASK FOR DATA (CLEARS CARRY) STA CSIPR0 STX CSIPR0+1 ;CSIPR0 = PTR TO PROPER BYTE IN CURSOR MASK JMP POKF1 ;WRITE THE DATA PAGE XPEEK: JSR DOLN ;SET UP LN0 - LN11 POINTERS IN CASE THEY ARE PEEKED JSR GETPARS ;GET CSI TYPE PARAMETERS LDX #0 ;X = 00 CMP #"M" ;MEMORY PEEK? BEQ PEKMEM CMP #"F" ;FONT PEEK? BNE RTS4 ;NO, IGNORE PEKFNT: ;PARAMETER 0 IS CHARACTER, PARAMETER 1 IS LINE. LDA CSIPR0+1 ;IF CHAR > 255, THEN IT'S A CURSOR FONT BNE PEKCUR LDY CSIPR1 ;Y = RASTER LINE INY INY ;Y = PAGE IN MEMORY FOR TABLE OF THOSE RASTER LINES STY CSIPR0+1 ;CSIPR0 = PTR TO PROPER BYTE IN CHARACTER GENERATOR PEKMEM: ;PARAMETER 0 IS ADDRESS. LDA (CSIPR0,X) ;ACC = DATA JMP PUTCHR ;SEND IT PEKCUR: LDA CSIPR1 ;ACC = RASTER LINE CLC ADC #CURMSK ;ACC = OFFSET IN CURSOR MASK FOR DATA (CLEARS CARRY) STA CSIPR0 STX CSIPR0+1 ;CSIPR0 = PTR TO PROPER BYTE IN CURSOR MASK JMP PEKMEM ;READ AND SEND THE DATA (ALWAYS BRANCHES) PAGE GOXSGR: JMP XSGR GOXUP: JMP XUP GOXBS: JMP XBS GOXDOWN:JMP XDOWN GOXRIGHT:JMP XRIGHT ;CSI RECEIVED, WAIT FOR UP TO 4 DECIMALLY SPECIFIED PARAMETERS, ; TERMINATED BY A COMMAND CHARACTER. XCSI: JSR GETPARS ;GET THE CSI PARAMETERS, RETURN WITH TERM CHAR IN Y ;ALL PARAMETERS RECEIVED. NOW, BASED ON THE TERMINATING CHARACTER, ; DO THE APPROPRIATE COMMAND, POSSIBLY USING THE PARAMETERS. CMP #"A" ;CURSOR UP? BEQ GOXUP CMP #"B" ;CURSOR DOWN? BEQ GOXDOWN CMP #"C" ;CURSOR RIGHT? BEQ GOXRIGHT CMP #"D" ;CURSOR LEFT? (BACKSPACE) BEQ GOXBS CMP #"K" ;ERASE IN LINE COMMAND? BEQ XEL CMP #"J" ;ERASE IN DISPLAY COMMAND? BEQ XED CMP #"m" ;SELECT GRAPHIC RENDITION COMMAND? BEQ GOXSGR CMP #"H" ;CURSOR POSITION COMMAND? BEQ XHVP CMP #"f" ;HORIZONTAL & VERTICAL POSITION COMMAND? BEQ XHVP CMP #"L" ;INSERT LINE COMMAND? BEQ XIL CMP #"M" ;DELETE LINE COMMAND? BEQ XDL JMP DOIT ;WRITE OR EXECUTE ALL OTHERS PAGE XEL: ;ERASE IN LINE, FROM CURSOR TO END OF LINE. JMP EREOL ;ERASE TO END OF LINE XED: ;ERASE IN DISPLAY, FROM CURSOR TO END OF DISPLAY IF 'ESC [ J' OR ; WHOLE DISPLAY IF 'ESC [ 2 J' LDA HCUR PHA ;SAVE CURRENT HORIZONTAL CURSOR, LDA VCUR PHA ;SAVE CURRENT VERTICAL CURSOR LDY 0,X ;GET NEXT TO LAST PARAMETER SENT CPY #02H ;IS IT A 2 ? BNE XPART ;YES, ERASE WHOLE SCREEN LDA #00 ;LOAD ACC WITH A ZERO FOR HOME POSITION STA HCUR ;SET HORIZONTAL CURSOR POSITION STA VCUR ;SET VERTICAL CURSOR POSITION XPART: JSR XED1 ;ERASE LINES PLA STA VCUR ;RESTORE VERTICAL AND PLA STA HCUR ; HORIZONTAL CURSOR RTS ;FORCE RE-COMPUTATION (FROM ABOVE) AND DONE XED1: JSR EREOL ;ERASE THE LINE LDA #0 STA HCUR ;MOVE TO THE BEGINNING OF INC VCUR ; THE NEXT LINE STA LNOK ;FORCE RE-COMPUTATION OF LN0 - LN11 LDA VCUR CMP #25 ;STILL LESS THAN THE (IMAGINARY) 25-TH. LINE? BCC XED1 ;YES, CONTINUE RTS ;RETURN FROM SUBROUTINE PAGE XHVP: XCUP: ;PREFERRED CURSOR POSITION COMMAND. ;THE DESIRED COORDINATES ARE IN THE CSI PARAMETERS. ;DEAL WITH THE X COORDINATE FIRST. LDX #0 ;DEFAULT IT TO 00 LDA CSIPR1+1 BNE CRX1 ;IF HOR POS'N > 255, DEFAULT TO POS'N 00 LDA CSIPR1 BEQ CRX1 ;IF HOR POS'N NOT SPECIFIED, DEFAULT IT TO 00 TAX DEX ;DECREMENT HOR POS'N SINCE SPEC SAYS COORDS START AT 1 CRX1: ;NOW DEAL SIMILARLY WITH THE Y COORDINATE. LDY #0 ;DEFAULT IT TO 00 LDA CSIPR0+1 BNE CRX2 ;IF LINE > 255, DEFAULT TO LINE 00 LDA CSIPR0 BEQ CRX2 ;IF LINE NOT SPECIFIED, DEFAULT IT TO 00 TAY DEY ;DECREMENT LINE SINCE SPEC SAYS COORDS START AT 1 CRX2: TSTCUR: ;PERFORM TESTS TO SEE IF REGISTERS X AND Y ARE LEGAL CURSOR VALUES IN ; THE RANGE 0 <= X <= 79, AND 0 <= Y <= 24. ;IF SO, MOVES CURSOR TO THE SPECIFIED COORDINATES. CPX #80 ;HORIZONTAL BEYOND END OF LINE? BCC TSTC1 ;NO, CONTINUE LDX #79 ;YES, DEFAULT IT TO THE END OF THE LINE TSTC1: CPY #25 ;VERTICAL BEYOND END OF SCREEN? BCC TSTC2 ;NO, CONTINUE LDY #24 ;YES, DEFAULT IT TO THE END OF THE SCREEN TSTC2: STX HCUR STY VCUR ;SET UP THE CURSOR VARIABLES JMP LNSNG ;FORCE RE-COMPUTATION AND DONE PAGE RTS8: RTS XIL: ;INSERT LINE. ;MOVE LINE N-1 TO LINE N; DO THIS STARTING AT 24 AND DECREMENTING. LDX LOGBOT ;START ACTION ON LAST LINE CPX VCUR ;COMPARE WITH CURRENT LINE BCC RTS8 ;CURSOR BELOW BOTTOM, DONE LDY VCUR ;STOP ON CURSOR'S LINE LDA #-1 ;DECREMENT BNE XDL3 ;CONTINUE (ALWAYS BRANCHES) XDL: ;DELETE LINE. ;MOVE LINE N+1 TO LINE N; DO THIS STARTING AT CURSOR AND INCREMENTING. LDX VCUR ;START ACTION ON CURSOR'S LINE LDY LOGBOT ;STOP ON LAST LINE CPY VCUR ;COMPARE WITH CURRENT LINE BCC RTS8 ;CURSOR BELOW BOTTOM, DONE LDA #1 ;INCREMENT XDL3: STA 12 ;SAVE +1 OR -1 FOR INCREMENTING OR DECREMENTING STY 13 ;SAVE STOPPING LINE LDA VCUR PHA ;SAVE THE CURSOR'S STARTING LINE STX VCUR ;MOVE THE CURSOR TO THE ACTION STARTING LINE LDA #0 STA HCUR ;MOVE CURSOR TO THE BEGINNING OF THIS LINE STA LNOK ;FORCE RE-COMPUTATION OF LN0 - LN11 XDL0: LDA VCUR ;ACC = CURSOR'S LINE CMP 13 ;HAVE WE REACHED THE STOPPING LINE? BEQ XDL9 ;YES, NOW CLEAR LAST LINE AND RETURN TO CURSOR'S LINE JSR DOLN ;SET UP LN0 - LN11 FOR LINE N LDX #5 XDL1: LDA LN0,X ;COPY LN0 - LN2 STA 6,X ; TO THE DESTINATION POINTERS DEX ;COPIED ALL 6 BYTES YET? BPL XDL1 ;NO, CONTINUE LDA VCUR CLC ADC 12 ;INCREMENT OR DECREMENT TO THE NEXT LINE STA VCUR JSR DOLN1 ;COMPUTE NEW LN0 - LN11 LDX #5 XDL2: LDA LN0,X ;COPY LN0 - LN2 STA 0,X ; TO THE SOURCE POINTERS DEX ;COPIED ALL 6 BYTES YET? BPL XDL2 ;NO, CONTINUE JSR MOVSUB ;MOVE SUB-CELL LINE POINTED TO BY 0,1 (TOP), ; 2,3 (MIDDLE), AND 4,5 (BOTTOM) TO SUB-CELL LINE ; POINTED TO BY 6,7 (TOP), 8,9 (MIDDLE), AND ; 10,11 (BOTTOM) JSR MOVSUB ;MOVE FOUR TIMES (ADDRESS OF SECOND SUB-CELL LINE IS JSR MOVSUB ; 80 AFTER THE FIRST, AND SO ON, SO IT IS UNNECESSARY JSR MOVSUB ; TO UPDATE THE ADDRESSES) JMP XDL0 ;REPEAT UNTIL LAST LINE HAS BEEN MOVED UP XDL9: JSR EREOL ;ERASE THE ENTIRE LAST LINE (ALSO SETS ATT TO ATTRIB) PLA STA VCUR JMP LNSNG ;FORCE RE-COMPUTATION AND DONE PAGE XRIGHT: INC HCUR ;GO TO THE RIGHT LDA HCUR EOR #80 ;BEYOND THE LAST (79TH.) CHARACTER? BNE XRGHT1 ;NO, DONE STA HCUR ;YES, GO TO POS'N 00 XDOWN: INC VCUR ;GO DOWN LDA VCUR EOR #25 ;BEYOND THE BOTTOM LINE? BNE XRGHT1 ;NO, DONE STA VCUR ;YES, GO TO LINE 00 XRGHT1: JMP LNSNG PAGE XSGR: ;ATTRIBUTE SETTING COMMAND RECEIVED, EXECUTE IT. LDX #CSIPR0-2 ;X = PTR TO THE FIRST PARAMETER - 2 ;SCAN ALL PARAMETERS, WHICH ARE REALLY SELECTORS, TURNING ON THE ;ATTRIBUTES AS SELECTED. ATRX0: INX INX ;GO TO THE NEXT PARAMETER LDY 1,X ;MOST SIG BYTE OF PARAMETER NON-ZERO? BNE ATRX1 ;YES, IGNORE IT LDY 0,X ;Y = THE SELECTOR ;SELECTOR = 0? BEQ ATOFF ;YES, TURN OFF ALL ATTRIBUTES LDA #01H ;HARDWARE CODE FOR BRIGHT CPY #1 ;SELECTOR = 1? BEQ ATON ;YES, TURN ON BRIGHT LDA #02H ;SOFTWARE CODE FOR UNDERLINE CPY #4 ;SELECTOR = 4? BEQ CONDON ;YES, TURN ON UNDERLINE LDA #02H ;HARDWARE CODE FOR BLINK CPY #5 ;SELECTOR = 5? BEQ ATON ;YES, TURN ON BLINK LDA #08H ;SOFTWARE CODE FOR REVERSE CPY #7 ;SELECTOR = 7? BNE ATRX1 ;NO, IGNORE SELECTOR ATON: SEI ;DISABLE INTERRUPTS ORA ATTRIB ;"OR" IN THE NEW ATTRIBUTE BITS ATON1: STA ATTRIB ;TELL THE SOFTWARE STA ATT ;TELL THE HARDWARE CLI ;RE-ENABLE INTERRUPTS ATRX1: CPX CSIPTR ;JUST FINISHED DOING THE LAST ATTRIBUTE? BEQ RTS2 ;YES, STOP CPX #CSIPRX - 2 ;JUST FINISHED DOING THE LAST IMPLEMENTED ATTR? BNE ATRX0 ;NO, CONTINUE RTS2: RTS ;YES, FINISHED ATOFF: LDA CONDS ;GET CONDITION BYTE AND #0FDH ;TURN OFF UNDERLINE BIT STA CONDS ;RESTORE CONDITION BYTE SEI ;DISABLE INTERRUPTS LDA ATTRIB AND #70H JMP ATON1 ;TURN OFF ALL ATTRIBUTES CONDON: ORA CONDS ;COMBINE UNDERLINE BIT WITH CONDITION BYTE STA CONDS ;RESTORE CONDITION BYTE BNE ATRX1 ;CONTINUE (ALWAYS BRANCHES) PAGE ;GRAPHICS ROUTINES. GOXLINE:JMP XLINE GOXARC: JMP XARC XGRPH: ;GRAPHICS. JSR GETPARS ;RECEIVE THE PARAMETERS, RETURN WITH Y = TERM CHAR CMP #"L" ;LINE? BEQ GOXLINE CMP #"M" ;MARKER? BEQ XMARK CMP #"T" ;TYPE? BEQ XTYPE CMP #"C" ;CURSOR? BEQ XGCUR CMP #"O" ;ARC? BEQ GOXARC CMP #"W" ;WRITE (POKE) BEQ XGPOKE CMP #"R" ;READ (PEEK) BEQ XGPEEK JMP DOIT ;WRITE ATTRIBUTE RAM FROM NEW ATTRIBUTES IN ATT LATCH ; GRFATT: SEI ;DISABLE INTERRUPTS LDA ATTRIB ;GET ATTRIBUTES ORA #04H ;SET BIT 2 TO ONE STA ATTRIB ;TELL SOFTWARE STA ATT ;TELL HARDWARE CLI ;RE-ENABLE INTERRUPTS RTS ;RETURN FROM SUBROUTINE XGPOKE: ;PAR0 IS X, PAR1 IS Y, PAR2 IS DATA BYTE, PAR3 IS ATTRIBUTES. JSR NEWGCUR ;PUT PARAMS TO (X,Y) LDA CSIPR3 AND #07H ; STA CSIPR3 ;STRIP ALL BUT ATTRIBUTE BITS AND DISABLE WRITE SEI ;DISABLE INTERRUPTS LDA ATTRIB AND #70H ;GET ONLY SCREEN BRIGHTNESS BITS ORA CSIPR3 ;COMBINE WITH ATTRIBUTE BITS STA ATT ;WRITE TO HARDWARE LDY #0 LDA (XYADDR),Y ;READ THE OLD SCREEN BYTE (AND MORE PARTICULARLY, THE ; CURRENT ATTRIBUTE BITS) IN CASE THE "STREAMING" ; ATTRIBUTE BIT WAS ON LDA CSIPR2 ;ACC = THE DATA BYTE STA (XYADDR),Y ;STORE IT ON THE SCREEN WITH SPECIFIED ATTRIBUTE LDA ATTRIB STA ATT ;RESTORE OLD ATTRIBUTES CLI ;RE-ENABLE INTERRUPTS RTS XGPEEK: ;PAR0 IS X, PAR1 IS Y. JSR NEWGCUR ;PUT PARAMS TO (X,Y) LDY #0 LDA (XYADDR),Y ;ACC = THE DATA BYTE FROM THE SCREEN JSR PUTCHR ;SEND THE DATA BYTE LDA XYMASK JMP PUTCHR ;SEND THE MASK FOR THE BIT ALSO XTYPE: ;SET UP THE DRAWING MODE AND THE LINE TYPE. ;PAR0 = DRAWING MODE, PAR1 = LINE TYPE IF NON-ZERO. LDA CSIPR0 STA XYOPR ;SET UP OPERATION LDA CSIPR1 BEQ RTS3 ;IF ZERO, LEAVE OLD LINE TYPE STA XYDOTS ;SET UP LINE TYPE STA TMPXYDOT ;BOTH OF THEM RTS3: RTS XGCUR: ;MOVE THE (X,Y) CURSOR WITHOUT DRAWING AND RESET THE TMPXYDOTS. ;PAR0 = X, PAR1 = Y. JMP NEWGCUR ;PUT PARAMS TO (X,Y) XMARK: ;DRAW A MARK (POINT). ;PAR0 = X, PAR1 = Y, PAR2 = FLAG: 0=DRAW A POINT, ELSE DRAW ASCII CHAR. ; JSR GRFATT ;TAKE CARE OF GRAPHIC ATTRIBUTES ; JSR NEWGCUR ;PUT PARAMS TO (X,Y) LDA CSIPR2 ;ARE WE TO DRAW A POINT? BNE XMRK1 ;NO, DRAW THE ASCII CHARACTER IN ACC JMP PNT ;YES, DRAW THE POINT XMRK1: STA 0 ;SAVE THE CHAR IN 0 ;WRITE A GIVEN CHARACTER TO THE DISPLAY AT A GIVEN GRAPHICS COORDINATE. ;ENTER: LOC. 0 = CHARACTER TO WRITE ; LOC. X & Y = COORDINATE ABOUT WHICH CHARACTER WILL BE CENTERED LDY #X LDX #4 JSR MOV2W ;TEMP SAVE (X,Y) IN 4,5 AND 6,7 ;POSITION THE X,Y GRAPHICS COORDINATES TO THE UPPER LEFT CORNER OF THE ; CHARACTER CELL PRIOR TO "SCANNING" THE CHARACTER TO THE DISPLAY. LDX #-3 STX XSTEP ;MOVE LEFT WRTG1: JSR DOXSTEP INX BNE WRTG1 ;THREE TIMES LDX #-6 STX YSTEP ;MOVE UP WRTG2: JSR DOYSTEP INX BNE WRTG2 ;SIX TIMES LDA #1 STA XSTEP STA YSTEP ;SET UP TO STEP TO THE RIGHT AND DOWN LDA #HIGH CGLN0 STA 1 ;0,1 = PTR TO TOP LINE OF CHAR IN CHAR GENERATOR ;SCAN THE 8 * 12 = 96 BITS OF THE CHARACTER. WRTG3: LDY #0 LDA (0),Y ;ACC = THE CURRENT RASTER LINE OF THE CHARACTER BEQ WRTG4 ;IF ALL ZEROS, DON'T BOTHER WRITING THIS LINE STA TMPXYDOT ;ALL THE "1" BITS IN THE CHARACTER WILL BE WRITTEN LDA #8 STA 2 ;LOC. 2 = LOOP COUNT LDA X PHA ;SAVE X-COORDINATE OF LEFT SIDE OF THE CHAR CELL LDA X+1 PHA WRTG5: JSR POINT ;PLOT THE POINT JSR DOXSTEP ;SCAN TO THE RIGHT DEC 2 ;MORE DOTS TO GO IN THIS BYTE? BNE WRTG5 ;YES, CONTINUE PLA STA X+1 PLA ;ACC = X-COORDINATE OF LEFT SIDE OF THE CHAR CELL STA X ;GO BACK TO THE LEFT SIDE JSR XYNG ;SET TO RE-CALCULATE THE XY VARIABLES WRTG4: JSR DOYSTEP ;ADVANCE TO THE NEXT LOWER RASTER LINE INC 1 ;UPDATE THE POINTER TO THE CHARACTER GENERATOR LDA 1 CMP #HIGH CGEND ;AT THE END OF THE CHARACTER GEN? BNE WRTG3 ;NO, CONTINUE LDY #4 LDX #X JSR MOV2W ;RESTORE ORIGINAL (X,Y) FROM 4,5 AND 6,7 LDA XYDOTS STA TMPXYDOT ;RESTORE THE DOTS TO THE GIVEN LINE TYPE JMP XYNG XLINE: ;DRAW ALL THE POINTS OF A LINE BETWEEN THE CURSOR AND (X1,Y1). ;PAR0 = X1, PAR1 = Y1. ; JSR GRFATT ;TAKE CARE OF GRAPHIC ATTRIBUTES ; LDY #CSIPR0 LDX #X1 JSR MOV2W ;COPY PAR0 AND 1 TO (X1,Y1) ;INITIALIZE XSTEP AND YSTEP TO POSITIVE AND NON-ZERO. LDY #1 STY XSTEP STY YSTEP DEY ;REG Y = 00 ;COMPUTE DELTA X AS DIFFERENCE BETWEEN X1 AND X. SEC LDA X1 SBC X STA XDELTA LDA X1+1 SBC X+1 STA XDELTA+1 ;XDELTA = X1 - X ;IF DELTA X IS NEGATIVE, MAKE IT POSITIVE AND MAKE XSTEP NEGATIVE. BPL L34 STA XSTEP ;XSTEP MADE NEGATIVE SEC TYA ;ACC = 00 SBC XDELTA STA XDELTA TYA ;ACC = 00 SBC XDELTA+1 STA XDELTA+1 ;DELTA X NEGATED L34: ;IF DELTA X IS ZERO, CHANGE XSTEP TO 0. ;ACC = XDELTA+1 FROM ABOVE ORA XDELTA ;BOTH HALVES 00? BNE L36 ;NO, CONTINUE STY XSTEP ;XSTEP MADE 0 L36: ;COMPUTE DELTA Y AS DIFFERENCE BETWEEN Y1 AND Y. SEC LDA Y1 SBC Y STA YDELTA LDA Y1+1 SBC Y+1 STA YDELTA+1 ;YDELTA = Y1 - Y ;IF DELTA Y IS NEGATIVE, MAKE IT POSITIVE AND MAKE YSTEP NEGATIVE. BPL L39 STA YSTEP ;YSTEP MADE NEGATIVE SEC TYA ;ACC = 00 SBC YDELTA STA YDELTA TYA ;ACC = 00 SBC YDELTA+1 STA YDELTA+1 ;DELTA Y NEGATED L39: ;IF DELTA Y IS 0, CHANGE YSTEP TO 0. ;ACC = YDELTA+1 FROM ABOVE ORA YDELTA ;BOTH HALVES 00? BNE L42 ;NO, CONTINUE STY YSTEP ;YSTEP MADE 0 L42: ;EVERYTHING'S SETUP. NOW EXAMINE VALUES TO SEE IF LINE IS FLATTER ; OR STEEPER THAN 45 DEGREES. SEC LDA YDELTA SBC XDELTA LDA YDELTA+1 SBC XDELTA+1 ;YDELTA - XDELTA BCS L99 ;YDELTA GREATER THAN OR EQUAL TO XDELTA: STEEP ;YDELTA IS LESS THAN XDELTA: FLAT. ;STEP X AND COMPUTE Y. ;INITIALIZE THE Y STEP CONTROL TO HALF DELTA X SO THAT FOR VERY VERY ; FLAT LINES, THE Y STEP WILL OCCUR NEAR THE MIDDLE, NOT RIGHT AT THE ; BEGINNING OR END. LDA XDELTA+1 LSR A STA VARS+1 LDA XDELTA ROR A STA VARS ;VARS = XDELTA / 2 L43X: ;PLOT ONE POINT AT (X,Y). JSR POINT ;SEE IF X HAS BEEN STEPPED TO X1. LDA X CMP X1 BNE L44X ;NO, CONTINUE LDA X+1 CMP X1+1 BNE L44X ;NO, CONTINUE RTS ;YES, DONE L44X: ;STEP X BY +1 OR -1 TO THE NEXT X COORDINATE CLOSER TO X1. JSR DOXSTEP ;X = X + XSTEP ;ADD DELTA Y TO VARS. LDY #YDELTA LDX #VARS JSR XPLUSY ;IF VARS + DELTA Y IS GREATER THAN OR EQUAL TO DELTA X, THEN ; DECREASE VARS BY DELTA X AND STEP Y. SEC LDA VARS SBC XDELTA TAX LDA VARS+1 SBC XDELTA+1 ;COMPUTE NEW VARS - DELTA X BCC L43X ;IF NEW VARS - DELTA X LESS THAN 0, LOOP ;ELSE, NEW VARS IS GREATER THAN OR EQUAL TO DELTA X. STX VARS STA VARS+1 ;VARS = VARS - DELTA X JSR DOYSTEP ;Y = Y + YSTEP JMP L43X ;LOOP L99: ;YDELTA IS GREATER THAN OR EQUAL TO XDELTA: STEEP. ;STEP Y AND COMPUTE X. ;INITIALIZE THE X STEP CONTROL TO HALF DELTA Y SO THAT FOR VERY VERY ; STEEP LINES, THE X STEP WILL OCCUR NEAR THE MIDDLE, NOT RIGHT AT THE ; BEGINNING OR END. LDA YDELTA+1 LSR A STA VARS+1 LDA YDELTA ROR A STA VARS ;VARS = YDELTA / 2 L143X: ;PLOT ONE POINT AT (X,Y). JSR POINT ;SEE IF Y HAS BEEN STEPPED TO Y1. LDA Y CMP Y1 BNE L144X ;NO, CONTINUE LDA Y+1 CMP Y1+1 BNE L144X ;NO, CONTINUE RTS ;YES, DONE L144X: ;STEP Y BY +1 OR -1 TO THE NEXT Y COORDINATE CLOSER TO Y1. JSR DOYSTEP ;Y = Y + YSTEP ;ADD DELTA X TO VARS. LDY #XDELTA LDX #VARS JSR XPLUSY ;IF VARS + DELTA X IS GREATER THAN OR EQUAL TO DELTA Y, THEN ; DECREASE VARS BY DELTA Y AND STEP X. SEC LDA VARS SBC YDELTA TAX LDA VARS+1 SBC YDELTA+1 ;COMPUTE NEW VARS - DELTA Y BCC L143X ;IF NEW VARS - DELTA Y LESS THAN 0, LOOP ;ELSE, NEW VARS IS GREATER THAN OR EQUAL TO DELTA Y. STX VARS STA VARS+1 ;VARS = VARS - DELTA Y JSR DOXSTEP ;X = X + XSTEP JMP L143X ;LOOP PAGE XARC: ;ARC PLOTTING ROUTINE ;A CIRCLE IS PLOTTED USING THE EQUATION: ; 2 2 ; X Y ; ------- + ------- = 1 OR ; 2 2 2 2 ; A R B R ; 2 2 2 2 2 2 2 ; Z = B X + A Y - A B R ;WITH Z BEING >0 OUTSIDE THE CIRCLE, 0 ON IT, AND <0 INSIDE IT. ;THE COEFICIENTS A AND B ARE SMALL INTEGERS WHICH REALLY MAKE THE ; MATHEMATICS APPLY TO AN ELLIPSE, BUT ARE HERE USED TO COMPENSATE ; FOR THE NON-SQUARE PIXEL ASPECT RATIO. WE WILL LET A = B = 1 ; WHEN WE WANT NO CORRECTION, OR A = 3, B = 2 WHEN WE DO. ;IF X INCREASES BY A SMALL AMOUNT, DX, THEN BY CALCULATION Z CHANGES ; BY THE AMOUNT: ; 2 2 2 ; DZ(X) = 2 B X DX + B DX ;SIMILARLY FOR Y: ; 2 2 2 ; DZ(Y) = 2 A Y DY + A DY ;A SIMILAR CALCULATION YIELDS THE CHANGE IN DZ(X) AND DZ(Y): ; 2 2 2 2 ; DDZ(X) = 2 B DX DDZ(Y) = 2 A DY ;NOW, DX AND DY MUST ALWAYS BE +1 OR -1 BECAUSE OF PIXEL CONSTRAINTS ; SO FOR A TRUE STEP IN EITHER THE X OR Y DIRECTION, THESE FORMULAS ; CAN BE SIMPLIFIED. ;WE COMPUTE THE LOCUS OF POINTS IN THE CIRCLE BY STEPPING THE ; INDEPENDANT COORDINATE, EITHER X OR Y, BY 1 OR -1 AND THEN ; PERFORMING A "TRIAL" STEP OF THE DEPENDANT COORDINATE BY 1/2 OR ; -1/2. THE RESULTING Z, COMPUTED BY ADDING THE TWO DZ'S TO THE ; ORIGINAL, TELLS US IF THE TRIAL POINT IS OUTSIDE OR INSIDE THE ; CIRCLE, AND THUS WHETHER A STEP SHOULD BE TAKEN BY THE DEPENDANT ; COORDINATE. ;THE EQUATIONS FOR DZ(X), DZ(Y), DDZ(X), DDZ(Y) (THE SECOND ORDER ; DIFFERENTIALS), AND DZT(X), DZT(Y) (FOR THE TRIAL STEPS) FOLLOW: ; (WITH DX AND DY + OR -1 FOR TRUE STEPS AND + OR -1/2 FOR TRIALS.) ; 2 2 2 2 ; DZ(X) = 2 B X DX + B DZ(Y) = 2 A Y DY + A ; 2 2 2 2 ; DZT(X) = 2 B X DX + B /4 DZT(Y) = 2 A Y DY + A /4 ; 2 2 ; DDZ(X) = 2 B DDZ(Y) = 2 A PAGE ;PAR0=RADIUS, PAR1=START X, PAR2=START Y, PAR3=END X, PAR4=END Y, ; PAR5 LOW = B SQUARED, PAR5 HIGH = A SQUARED (IF BOTH ARE ZERO, ; THEN USE 4 AND 9) ; JSR GRFATT ;TAKE CARE OF GRAPHIC ATTRIBUTES ; ;INITIALIZE TMPXYDOT ALWAYS TO A KNOWN STATE. LDA XYDOTS STA TMPXYDOT ;IF RADIUS IS ZERO, PLOT ONLY THE SINGLE POINT AND QUIT. LDA CSIPR0 ORA CSIPR0+1 ;RADIUS = 0? BNE ARC00 ;NO, CONTINUE JMP PNT ;YES, PLOT AND DONE ARC00: ;SET UP THE PIXEL ASPECT RATIO. IF PAR5 IS ZERO, USE B=2, A=3. ; OTHERWISE, PAR5 LOW IS B SQUARED, PAR5 HIGH IS A SQUARED. LDX CSIPR5 ;X = B SQUARED, IF GIVEN LDY CSIPR5+1 ;Y = A SQUARED, IF GIVEN BNE ARC0 ;ASPECT GIVEN, USE AS GIVEN LDX #4 ;ELSE, SET B SQUARED = 4 AND LDY #9 ; A SQUARED = 9 ARC0: STX BSQ STY ASQ LDA #0 STA BSQ+1 STA ASQ+1 ;SAVE THE VALUES AWAY AS WORDS ;INITIALIZE Z, THE "ERROR" TERM, TO ZERO. STA Z STA Z+1 ;SAVE THE CURRENT GRAPHICS CURSOR POSITION (THE CENTER) IN (XC,YC). LDY #X ;(X,Y) = SOURCE LDX #XC ;(XC,YC) = DESTINATION JSR MOV2W ;MOVE BOTH X AND Y ;SEE IF A FULL CIRCLE IS TO BE DRAWN (IF START AND END POINTS ARE 0). LDX #7 ;"OR" EIGHT BYTES (FOUR WORDS) LDA #0 ARC1: ORA CSIPR1,X ;"OR" TOGETHER START AND END, X AND Y DEX BPL ARC1 ;LOOP UNTIL ALL "OR"S COMPLETE TAX ;TEST ACC BNE XARC1 ;ARC, NOT FULL CIRCLE, CONTINUE ;FULL CIRCLE, SET UP PARAMETERS AS IF ARC OF 360 DEGREES WAS ASKED FOR. ;COPY CENTER TO START XY. LDX #CSIPR1 ;PARAMETER 1 IS START X JSR MOV2W ;ADD RADIUS TO START Y. LDY #CSIPR0 ;PARAMETER 0 IS RADIUS LDX #CSIPR2 JSR XPLUSY ;COPY START XY TO END XY. LDY #CSIPR1 LDX #CSIPR3 ;PARAMETER 3 IS END X JSR MOV2W ;MAKE END X BE ONE MORE SO END POINT FALLS IN QUADRANT I. INC CSIPR3 BNE ARC2 INC CSIPR3+1 ARC2: XARC1: ;THE VARIABLES (X,Y) ARE USED TO PLOT THE POINTS. INITIALIZE THEM TO ; THE START XY VALUES. LDY #CSIPR1 LDX #X JSR MOV2W JSR XYNG ;XY HAS BEEN CHANGED ;THE START AND END COORDINATES ARE GIVEN AS ABSOLUTE. COMPUTE THEM ; RELATIVE TO THE CIRCLE'S CENTER. LDY #XC LDX #CSIPR1 JSR XMINUSY LDX #CSIPR3 JSR XMINUSY LDY #YC LDX #CSIPR2 JSR XMINUSY LDX #CSIPR4 JSR XMINUSY ;DETERMINE AND SAVE AWAY THE QUADRANT OF THE END POINT. LDY #CSIPR3 LDX #X1 JSR MOV2W JSR QUADRNT ;DETERMINE THE QUADRANT OF (X1,Y1) BPL XARC2 ;NOT AT THE CENTER, CONTINUE ENDNG: JSR PNT ;AT THE CENTER, JUST PLOT ONE POINT JMP XACDUN XARC2: STA ENDQUAD ;SAVE THE RESULT ;(X1,Y1) ARE USED AS THE CALCULATING VARIABLES; INITIALIZE THEM TO ; THE START XY. LDY #CSIPR1 JSR MOV2W JSR DIFFS ;COMPUTE THE DIFFERENTIALS BMI ENDNG ;END XY IS AT THE CENTER OF THE CIRCLE, ERROR ;INITIALIZE Z TO DZT(X) OR DZT(Y), WHICHEVER IS NEGATIVE. LDY #DZTX LDX #Z LDA DZTX+1 BMI ARC3 ;DZT(X) IS NEGATIVE, USE IT LDY #DZTY LDA DZTY+1 BPL ARC4 ;DZT(Y) IS POSITIVE TOO, USE ZERO ARC3: JSR MOV1W ;INITIALIZE Z ARC4: ;ENTER THE CIRCLE DRAWING LOOP AT ONE OF FOUR ENTRY POINTS, DEPENDING ; ON THE CURRENT QUADRANT. LDX QUAD BEQ Q1ENT DEX BEQ Q2ENT DEX BEQ Q3ENT BNE Q4ENT ;(ALWAYS BRANCHES) Q1A: JSR YY ;PLOT A POINT, STEP Y AS INDEPENDANT AND X AS DEPENDANT BEQ XACDUN ;REACHED END POINT, DONE Q1ENT: JSR TRANS ;ARE WE AT THE TRANSITION POINT, ABOUT 45 DEGREES? BMI Q1A ;NO, CONTINUE STEPPING BEQ XACDUN ;YES, AND THE END POINT IS THERE TOO, DONE ;SWITCH THE ROLES OF X AND Y. Q1B: LDA X1 ORA X1+1 ;ARE WE AT THE END OF THE QUADRANT, THE Y AXIS? BEQ Q1C ;YES, DONE JSR XX BNE Q1B BEQ XACDUN ;DONE IF WE HIT STOP POINT Q1C: JSR DIFFS ;RE-COMPUTE THE DIFFERENTIALS FOR QUADRANT II BMI ENDNG ;END XY IS AT THE CENTER OF THE CIRCLE, ERROR Q2A: JSR XX ;PLOT A POINT, STEP X AS INDEPENDANT AND Y AS DEPENDANT BEQ XACDUN ;REACHED END POINT, DONE Q2ENT: JSR TRANS ;ARE WE AT THE TRANSITION POINT, ABOUT 45 DEGREES? BMI Q2A ;NO, CONTINUE STEPPING BEQ XACDUN ;YES, AND THE END POINT IS THERE TOO, DONE ;SWITCH THE ROLES OF X AND Y. Q2B: LDA Y1 ORA Y1+1 ;ARE WE AT THE END OF THE QUADRANT, THE X AXIS? BEQ Q2C ;YES, DONE JSR YY BNE Q2B BEQ XACDUN ;DONE IF WE HIT STOP POINT Q2C: JSR DIFFS ;RE-COMPUTE THE DIFFERENTIALS FOR QUADRANT III BMI ENDNG ;END XY IS AT THE CENTER OF THE CIRCLE, ERROR Q3A: JSR YY ;PLOT A POINT, STEP Y AS INDEPENDANT AND X AS DEPENDANT BEQ XACDUN ;REACHED END POINT, DONE Q3ENT: JSR TRANS ;ARE WE AT THE TRANSITION POINT, ABOUT 45 DEGREES? BMI Q3A ;NO, CONTINUE STEPPING BEQ XACDUN ;YES, AND THE END POINT IS THERE TOO, DONE ;SWITCH THE ROLES OF X AND Y. Q3B: LDA X1 ORA X1+1 ;ARE WE AT THE END OF THE QUADRANT, THE Y AXIS? BEQ Q3C ;YES, DONE JSR XX BNE Q3B BEQ XACDUN ;DONE IF WE HIT STOP POINT Q3C: JSR DIFFS ;RE-COMPUTE THE DIFFERENTIALS FOR QUADRANT IV BPL Q4A ;XY OK, CONTINUE JMP ENDNG ;END XY IS AT THE CENTER OF THE CIRCLE, ERROR Q4A: JSR XX ;PLOT A POINT, STEP X AS INDEPENDANT AND Y AS DEPENDANT BEQ XACDUN ;REACHED END POINT, DONE Q4ENT: JSR TRANS ;ARE WE AT THE TRANSITION POINT, ABOUT 45 DEGREES? BMI Q4A ;NO, CONTINUE STEPPING BEQ XACDUN ;YES, AND THE END POINT IS THERE TOO, DONE ;SWITCH THE ROLES OF X AND Y. Q4B: LDA Y1 ORA Y1+1 ;ARE WE AT THE END OF THE QUADRANT, THE X AXIS? BEQ Q4C ;YES, DONE JSR YY BNE Q4B BEQ XACDUN ;DONE IF WE HIT STOP POINT Q4C: JSR DIFFS ;RE-COMPUTE THE DIFFERENTIALS FOR QUADRANT I BPL Q1A ;OK, CONTINUE JMP ENDNG ;END XY IS AT THE CENTER OF THE CIRCLE, ERROR XACDUN: LDY #XC LDX #X JSR MOV2W ;RESTORE THE CENTER (XC,YC) TO THE CURSOR POS'N, (X,Y) JMP XYNG PAGE ;>>>>>>> S U B R O U T I N E S <<<<<<< DISP: ;WRITE THE FONT REPRESENTATION OF THE CHARACTER IN ACC TO THE SCREEN ; AT THE CURRENT CURSOR POSITION. ;DURING THE WRITING, THE CURRENT ATTRIBUTES FOR BRIGHT AND BLINK WILL ; BE AUTOMATICALLY ADDED TO THE MEMORY AS EACH BYTE IS WRITTEN. ; HOWEVER, THE REVERSE AND UNDERLINE ATTRIBUTES MUST BE EXPLICITLY ; DONE BY THE SOFTWARE. ;INPUT: ACC THE CHARACTER, 00 - FF ; ATTRIB THE CURRENT ATTRIBUTES. ; CGLN0 THE FONT TABLES FOR THE CHARACTERS, 12 TABLES, ONE FOR ; THRU EACH OF THE 12 RASTER LINES. EACH TABLE HOLDS RASTER ; CGLN11 LINE N OF ALL 256 CHARACTERS. ; LN0 POINTERS TO THE BYTES OF THE CHARACTER AT THE CURRENT ; THRU CURSOR POSITION. THESE ADDRESSES ARE KEPT UP-TO-DATE ; LN11 BY THE DOLN ROUTINE. ;WRITE ATTRIBUTE RAM FROM NEW ATTRIBUTES IN ATT LATCH ; PHA ;SAVE ACC SEI ;DISABLE INTERRUPTS LDA ATTRIB ;GET ATTRIBUTES ORA #04H ;SET BIT 2 TO ONE STA ATTRIB ;TELL SOFTWARE STA ATT ;TELL HARDWARE CLI ;RE-ENABLE INTERRUPTS PLA ;RESTORE SAVED ACC LDY LNOK ;LN0 - LN11 POINTERS UP-TO-DATE? BNE DISP8 ;YES, CONTINUE JSR DOLN1 ;NO, UPDATE THEM DISP8: ORA SOFLG ;OR THE CHARACTER WITH THE SHIFT OUT FLAG TO POSSIBLY ; SET BIT 7 HIGH CLC BPL DISP0A ;USE G0 CHARACTER SET SINCE BIT 7 IS LOW AND #7FH ;STRIP BIT 7 ADC G1VAL ;USE G1 CHARACTER SET JMP DISP0B ;CONTINUE DISP0A: ADC G0VAL DISP0B: TAY ;Y = THE CHARACTER LDX #0 ;X = 00 BIT CONDS ;IN OVERSTRIKE MODE? BPL DISP1 ;NO, REPLACE THE OLD CHARACTER WITH THE NEW CHARACTER ;OVERSTRIKE THE CHARACTER RATHER THAN REPLACING IT. ;CONDITIONALLY UN-REVERSE THE CHARACTER AT THE CURSOR POS'N BUT ONLY ; IF IT SEEMS NOT TO BE A SPACE, I.E. NOT ALL ZEROS. LDA (LN2,X) ORA (LN5,X) ORA (LN8,X) ;TEST A FEW LINES OF THE CHARACTER BEQ DISP0 ;IF NOT ALREADY REVERSED, DON'T UN-REVERSE STY 0 ;TEMP SAVE THE CHAR JSR REVCHR ;REMOVE THE REVERSAL ONLY IF WE ARE IN THE REVERSE MODE LDY 0 ;RESTORE IT DISP0: ;FOR EACH OF THE TWELVE RASTER LINES, LDA CGLN0,Y ;GET CHAR GEN CONTENTS, ORA (LN0,X) ; OR IT WITH THE CURRENT CHARACTER, STA (LN0,X) ; AND STORE IT IN MEMORY. LDA CGLN1,Y ORA (LN1,X) STA (LN1,X) LDA CGLN2,Y ORA (LN2,X) STA (LN2,X) LDA CGLN3,Y ORA (LN3,X) STA (LN3,X) LDA CGLN4,Y ORA (LN4,X) STA (LN4,X) LDA CGLN5,Y ORA (LN5,X) STA (LN5,X) LDA CGLN6,Y ORA (LN6,X) STA (LN6,X) LDA CGLN7,Y ORA (LN7,X) STA (LN7,X) LDA CGLN8,Y ORA (LN8,X) STA (LN8,X) LDA CGLN9,Y ORA (LN9,X) STA (LN9,X) LDA CGLN10,Y ORA (LN10,X) STA (LN10,X) LDA CGLN11,Y ORA (LN11,X) STA (LN11,X) JMP DISP2 ;CONTINUE DISP1: ;FOR EACH OF THE TWELVE RASTER LINES, LDA CGLN0,Y ;GET CHAR GEN CONTENTS STA (LN0,X) ; AND STORE IT IN MEMORY LDA CGLN1,Y STA (LN1,X) LDA CGLN2,Y STA (LN2,X) LDA CGLN3,Y STA (LN3,X) LDA CGLN4,Y STA (LN4,X) LDA CGLN5,Y STA (LN5,X) LDA CGLN6,Y STA (LN6,X) LDA CGLN7,Y STA (LN7,X) LDA CGLN8,Y STA (LN8,X) LDA CGLN9,Y STA (LN9,X) LDA CGLN10,Y STA (LN10,X) LDA CGLN11,Y STA (LN11,X) DISP2: ;SEE IF FIX-UP IS NEEDED FOR THE SOFTWARE ATTRIBUTES. LDA CONDS ;GET CONDITION BYTE AND #02H ;ISOLATE UNDERLINE BIT BEQ DISP2A ;NO UNDERLINE, SO CONTINUE LDA #0FFH STA (LN10,X) ;UNCONDITIONALLY TURN ON THE UNDERLINE DISP2A: JSR REVCHR ;REVERSE THE CHARACTER IF REVERSE ATTRIBUTE IS ON ;NOW INCREMENT THE CURSOR IF IT IS NOT ALREADY ON THE LAST POSITION ; OF THE LINE. LDA HCUR CMP #79 ;CURSOR CURRENTLY AT THE END OF THE LINE? BNE DISP7 ;NO, INCREMENT CURSOR AND CONTINUE ;FALLING OFF THE END OF A LINE WE MUST EXAMINE STATE OF AUTO NEWLINE. LDA CONDS AND #08H ;AUTO NEWLINE ON? BEQ RTS9 ;NO, JUST STAY AT THE END OF THE LINE JSR XCR ;YES, MOVE CURSOR TO BEGINNING OF JMP XLF ; THE NEXT LINE RTS9: RTS DISP7: INC HCUR ;INCREMENT THE SOFTWARE CURSOR ;INCREMENT ALL THE POINTERS TO THE CURSOR CHARACTER'S RASTER LINES. ;FIRST DO THE FIRST SUB-CELL. INC LN0 ;LEAST SIG BYTES OF SUB-CELL LDA LN0 STA LN1 ;(ALL THESE POINTERS SHOULD HAVE THE SAME VALUE) STA LN2 BNE DISP3 ;NO OVERFLOW, CONTINUE ;OVERFLOW, FIX IT UP. INC LN0+1 ;MOST SIG BYTES OF SUB-CELL INC LN1+1 ;(THESE BYTES ARE OFFSET BY 20H OR 2000H IN ADDRESS) INC LN2+1 ;THIS BYTE WILL INCREMENT FROM 7FH TO 80H ON OVERFLOW BPL DISP3 ;IF NO WRAP AROUND NEEDED, CONTINUE LDA #60H STA LN2+1 ;PUT 6000H INTO LN2 LDA #40H STA LN1+1 ;PUT 4000H INTO LN1 LSR A ;CONVERT 40H TO 20H STA LN0+1 ;PUT 2000H INTO LN0 DISP3: ;DO THE SAME FOR THE SECOND SUB-CELL. INC LN3 ;LEAST SIG BYTES OF SUB-CELL LDA LN3 STA LN4 ;(ALL THESE POINTERS SHOULD HAVE THE SAME VALUE) STA LN5 BNE DISP4 ;NO OVERFLOW, CONTINUE ;OVERFLOW, FIX IT UP. INC LN3+1 ;MOST SIG BYTES OF SUB-CELL INC LN4+1 ;(THESE BYTES ARE OFFSET BY 20H OR 2000H IN ADDRESS) INC LN5+1 ;THIS BYTE WILL INCREMENT FROM 7FH TO 80H ON OVERFLOW BPL DISP4 ;IF NO WRAP AROUND NEEDED, CONTINUE LDA #60H STA LN5+1 ;PUT 6000H INTO LN5 LDA #40H STA LN4+1 ;PUT 4000H INTO LN4 LSR A ;CONVERT 40H TO 20H STA LN3+1 ;PUT 2000H INTO LN3 DISP4: ;DO THE SAME FOR THE THIRD SUB-CELL. INC LN6 ;LEAST SIG BYTES OF SUB-CELL LDA LN6 STA LN7 ;(ALL THESE POINTERS SHOULD HAVE THE SAME VALUE) STA LN8 BNE DISP5 ;NO OVERFLOW, CONTINUE ;OVERFLOW, FIX IT UP. INC LN6+1 ;MOST SIG BYTES OF SUB-CELL INC LN7+1 ;(THESE BYTES ARE OFFSET BY 20H OR 2000H IN ADDRESS) INC LN8+1 ;THIS BYTE WILL INCREMENT FROM 7FH TO 80H ON OVERFLOW BPL DISP5 ;IF NO WRAP AROUND NEEDED, CONTINUE LDA #60H STA LN8+1 ;PUT 6000H INTO LN8 LDA #40H STA LN7+1 ;PUT 4000H INTO LN7 LSR A ;CONVERT 40H TO 20H STA LN6+1 ;PUT 2000H INTO LN6 DISP5: ;DO THE SAME FOR THE LAST SUB-CELL. INC LN9 ;LEAST SIG BYTES OF SUB-CELL LDA LN9 STA LN10 ;(ALL THESE POINTERS SHOULD HAVE THE SAME VALUE) STA LN11 BNE RTS10 ;NO OVERFLOW, DONE ;OVERFLOW, FIX IT UP. INC LN9+1 ;MOST SIG BYTES OF SUB-CELL INC LN10+1 ;(THESE BYTES ARE OFFSET BY 20H OR 2000H IN ADDRESS) INC LN11+1 ;THIS BYTE WILL INCREMENT FROM 7FH TO 80H ON OVERFLOW BPL RTS10 ;IF NO WRAP AROUND NEEDED, CONTINUE LDA #60H STA LN11+1 ;PUT 6000H INTO LN11 LDA #40H STA LN10+1 ;PUT 4000H INTO LN10 LSR A ;CONVERT 40H TO 20H STA LN9+1 ;PUT 2000H INTO LN9 RTS10: RTS PAGE CURGET: ;INITIALIZE THE PHOSPHOR SAVER ATTRIBUTE BYTE. LDA #4 STA PSAVCNT ;INITIALIZE 4-MINUTE COUNT TO 16 MINUTES CURG2: ;WAIT A CERTAIN AMOUNT OF TIME FOR THE Z-80 TO PASS ANOTHER CHAR. INC CURBLK BNE CURG1 ;NO OVERFLOW, CONTINUE ;OK, THE Z-80 ISN'T PASSING CHARS TO US, LOOK AT THE PHOSPHOR SAVER. INC CURBLK + 1 ;INCREMENT THE SECOND CURSOR BLINK COUNTER BNE CURG3 ;NO OVERFLOW, CONTINUE INC CURBLK + 2 ;INCREMENT THE PHOSPHOR SAVER COUNTER BNE CURG3 ;NO OVERFLOW, CONTINUE ;COME HERE EVERY 4 MINUTES. LDA PSAVCNT BEQ CURG3 ;ALREADY BLANK, DONE DEC PSAVCNT ;DECREMENT 4-MINUTE COUNT BNE CURG3 ;NOT TO 16 MINS YET, CONTINUE LDA CONDS AND #04H BNE CURG3 ;PHOSPHOR SAVER DISABLED, DONE SEI ;DISABLE INTERRUPTS LDA ATTRIB ORA #20H STA ATTRIB STA ATT ;BLANK THE SCREEN CLI ;RE-ENABLE INTERRUPTS ; LDA #0FFH ;COMMAND TO Z-80 THAT PHOSPHOR SAVER IN EFFECT JSR IPUTCHR ;INTERRUPT Z-80 ; CURG3: ;EVERY 256 COUNT, CHECK THE CURSOR. LDA #20H ;MASK FOR CURSOR BLINK BIT CONDS ;CURSOR WANTED? BVC CURG1 ;NO, MERELY WAIT FOR THE NEXT CHARACTER BEQ ONGET ;YES, BUT NO BLINK, TURN ON THE CURSOR ;CURSOR BLINK IN THE FOLLOWING MANNER: 75% ON, 25% OFF. BIT CURBLK+1 ;TEST COUNTER VALUE BPL ONGET ;TURN ON CURSOR IF B7 = 0 BVC ONGET ;TURN ON CURSOR IF B7 = 1 AND B6 = 0 JSR CUROFF ;TURN OFF CURSOR JMP CURG1 ONGET: JSR CURON ;TURN ON THE CURSOR CURG1: LDA IOPC ;READ PORT C FOR STATUS BITS AND #08H ;BYTE HERE? BEQ CURG2 ;NO, PC3 = 0, LOOP AND WAIT ;BYTE HERE, TURN OFF THE CURSOR, RESET THE BLINK VARIABLES, GET BYTE. JSR CUROFF ;TURN OFF THE CURSOR SEI ;DISABLE INTERRUPTS LDA ATTRIB AND #0DFH ;TURN SCREEN BACK ON STA ATTRIB STA ATT ;UPDATE HARDWARE CLI ;RE-ENABLE INTERRUPTS LDA #0 STA CURBLK STA CURBLK+1 ;CLEAR THE CURSOR BLINK COUNTER SO THE CURSOR WILL ; START OFF IN THE ON STATE STA CURBLK+2 ;RESET THE PHOSPHOR SAVER COUNT TOO GETCHR: ;WAIT FOR A CHARACTER FROM THE DISPLAY SECTION, RETURN IT IN ACC. LDA IOPC ;READ PORT C FOR STATUS BITS AND #08H ;BYTE HERE? BEQ CURGET ;NO, PC3 = 0, LOOP AND WAIT ;INPUT THE BYTE FROM THE PROCESSING SECTION. LDA IOPA ;ACC = THE BYTE ;ACCEPT BYTE FROM PROCESSING SECTION. LDX #0EH ;MASK TO RESET PORT C, BIT 7 STX IOCTRL ;RESET IT INX ;MASK TO SET PORT C, BIT 7 STX IOCTRL ;SET IT AGAIN RTS ;RETURN WITH THE CHARACTER IN ACC. CUROFF: ;TURN OFF THE SOFTWARE CURSOR. LDA CURDSP ;CURSOR ALREADY ON? BMI CURTOG ;YES, TURN IT OFF CO1: RTS ;NO, DONE CURON: ;TURN ON THE SOFTWARE CURSOR. LDA CURDSP ;CURSOR ALREADY ON? BMI CO1 ;YES, DONE CURTOG: ;TOGGLE THE SOFTWARE CURSOR. EOR #80H ;TOGGLE BIT 7 STA CURDSP ;TOGGLE THE CURSOR DISPLAYED FLAG JSR DOLN ;RE-COMPUTE THE LN0 - LN11 POINTERS LDY #CURMSK ;Y = POINTER TO THE CURSOR MASK ON PAGE 00 JMP EORCHR ;TURN THE CURSOR ON OR OFF ;NO NEED TO RESTORE THE ATTRIBUTES; THEY AREN'T BEING ; WRITTEN AND WILL BE RESTORED LATER WHEN THE NEXT ; CHARACTER ARRIVES. PAGE PUTCHR: ;OUTPUT A CHARACTER TO THE PROCESSING SECTION. STA IOPB ;OUTPUT THE CHARACTER LDA #0CH ;MASK TO RESET PORT C, BIT 6 STA IOCTRL ;RESET IT LDA #0DH ;MASK TO SET PORT C, BIT 6 STA IOCTRL ;SET IT PCH1: LDA IOPC ;READ PORT C FOR STATUS BITS AND #08H ;BYTE HERE? BEQ PCH2 ;NO, PC3 = 0, CONTINUE LDA #NUL ;BYTE FROM PROCESSING SECTION, JMP DOIT ; FIX UP STACK AND PROCESS IT PCH2: LDA IOPC ;READ PORT C FOR STATUS BITS AND #01H ;PROCESSING SECTION READY? BEQ PCH1 ;NO, PC0 = 0, LOOP AND WAIT RTS IPUTCHR: ;INTERRUPT AND THEN OUTPUT A CHARACTER TO THE PROCESSING SECTION. STA IOPB ;OUTPUT THE CHARACTER LDA #0CH ;MASK TO RESET PORT C, BIT 6 STA IOCTRL ;RESET IT LDA #0DH ;MASK TO SET PORT C, BIT 6 STA IOCTRL ;SET IT LDA #01H STA Z80 ;INTERRUPT THE Z-80 BNE PCH2 ;WAIT FOR ACKNOWLEDGEMENT PAGE GETPARS:;ACCEPT PARAMETERS AS FOR A COMMAND STRING INTRODUCER (CSI). ;RETURN WITH THE PARAMETERS STARTING AT CSIPR0, ; POINTER TO LAST RECEIVED PARAMETER IN X AND CSIPTR, ; (WITH X AND CSIPTR = CSIPRX IF TOO MANY RECEIVED) ; AND TERMINATING CHARACTER IN ACC AND Y. ;CLEAR OUT THE PARAMETERS TO ALL ZEROS AND INIT THE PARAM POINTER. LDX #CSIPRX ;X = PTR TO LAST PARAMETER LDA #0 ;ACC = 00 GETP1: DEX STA 0,X ;CLEAR THE PARAMETER CPX #CSIPR0 BNE GETP1 GETP2: STX CSIPTR ;INITIALIZE PARA POINTER TO FIRST PARAMETER ;NOW ACCEPT AND PARSE THE PARAMETERS. PARLUP: JSR GETCHR ;GET THE NEXT CHARACTER PARLUP1: LDX CSIPTR ;X = PTR TO CURRENT PARAMETER TAY ;SAVE THE CHAR AND #0F0H ;ISOLATE UPPER NIBBLE CMP #30H ;TEST FOR AN ASCII NUMERIC BNE GETPDUN ;NO, TERMINATING CHARACTER, DONE TYA ;ACC = THE CHARACTER AGAIN CMP #"=" ;BINARY MODE INDICATOR? BNE PARL1 ;NO, CONTINUE ;YES, TWO BYTES FOLLOW, LOW THEN HIGH BYTE. JSR GETCHR ;GET LOW BYTE PHA ;SAVE IT JSR GETCHR ;GET HIGH BYTE LDX CSIPTR ;X = PTR TO CURRENT PARAMETER STA 1,X ;SECOND BYTE IS HIGH BYTE PLA STA 0,X ;FIRST IS LOW JMP PARLUP ;LOOK FOR THE FOLLOWING SEMICOLON PARL1: CMP #";" ;PARAMETER TERMINATOR? BEQ NXTPAR ;YES, ADVANCE TO THE NEXT PARAMETER ;CONTINUATION OF THE CURRENT PARAMETER. INCLUDE THIS DIGIT BY ; MULTIPLYING THE OLD PARAMETER BY 10 AND THEN ADDING THE NEW DIGIT ; TO IT. LDA 1,X PHA ;PUSH MOST SIG BYTE OF CURRENT PARA LDA 0,X ;ACC = LEAST SIG BYTE OF CURRENT PARA ASL 0,X ROL 1,X ;CURRENT PARA MULTIPLIED BY 2 ASL 0,X ROL 1,X ;NOW BY 4 CLC ADC 0,X ;ACC = (CURRENT PARA * 5) LOW STA 0,X ;SAVE IT PLA ADC 1,X ;ACC = (CURRENT PARA * 5) HIGH STA 1,X ;SAVE IT ASL 0,X ROL 1,X ;CURRENT PARA NOW MULTIPLIED BY 10 TYA ;ACC = THE NEW DIGIT JUST RECEIVED AND #0FH ;STRIP TO GET NUMBER FROM 00H TO 09H CLC ADC 0,X STA 0,X ;ADD NEW DIGIT TO 10 TIMES OLD PARA BCC PARLUP ;IF NO CARRY, WAIT FOR NEXT DIGIT INC 1,X ;INCLUDE CARRY IN PARA BCS PARLUP ;ALWAYS BRANCHES NXTPAR: ;SEMICOLON RECEIVED, ADVANCE TO THE NEXT PARAMETER. CPX #CSIPRX ;MORE THAN FOUR PARAMETERS RECEIVED SO FAR? BEQ PARLUP ;YES, TOO MANY, IGNORE ANY MORE BY "STICKING" AT THIS ; CSIPRX PARAMETER INX INX BNE GETP2 ;INCR PARA PTR TO NEXT PARA & LOOP (ALWAYS BRANCHES) GETPDUN:TYA ;EXIT WITH TERMINATING CHAR IN ACC RTS PAGE REVCHR: ;REVERSE OR UN-REVERSE THE CHARACTER AT THE CURSOR POS'N. TEST THE ; REVERSE BIT OF THE ATTRIB BYTE TO DECIDE IF THE REVERSAL IS NEEDED. LDA ATTRIB AND #08H ;REVERSE ATTRIBUTE ON? BEQ RVCH1 ;NO, DO NOTHING LDY #REVMSK ;POINT Y TO THE REVERSE MASK EORCHR: ;EXCLUSIVE-OR THE CHARACTER POINTED TO BY THE LN0 THROUGH LN11 ; VARIABLES WITH THE CHARACTER, ON PAGE 00, POINTED TO BY REGISTER Y. LDX #0 ;X = 00 LDA (LN0,X) ;GET THE BYTE EOR 0,Y ;EXCLUSIVE OR IT STA (LN0,X) ;STORE IT BACK LDA (LN1,X) EOR 1,Y STA (LN1,X) LDA (LN2,X) EOR 2,Y STA (LN2,X) LDA (LN3,X) EOR 3,Y STA (LN3,X) LDA (LN4,X) EOR 4,Y STA (LN4,X) LDA (LN5,X) EOR 5,Y STA (LN5,X) LDA (LN6,X) EOR 6,Y STA (LN6,X) LDA (LN7,X) EOR 7,Y STA (LN7,X) LDA (LN8,X) EOR 8,Y STA (LN8,X) LDA (LN9,X) EOR 9,Y STA (LN9,X) LDA (LN10,X) EOR 10,Y STA (LN10,X) LDA (LN11,X) EOR 11,Y STA (LN11,X) RVCH1: RTS PAGE EREOL: ;ERASE FROM CURSOR POS'N TO END OF LINE. JSR DOLN ;RE-COMPUTE THE LN0 - LN11 POINTERS LDA #80 SEC SBC HCUR ;ACC = 80 - HORIZONTAL CURSOR = # OF CHARS TO THE END TAX ;X = # OF CHARS STX 6 ;TEMP SAVE # OF CHARS LDY LN0 LDA LN0+1 JSR CLRSUB ;CLEAR THE FIRST SUB-CELL LDY LN3 LDA LN3+1 LDX 6 JSR CLRSUB ;CLEAR THE SECOND SUB-CELL LDY LN6 LDA LN6+1 LDX 6 JSR CLRSUB ;CLEAR THE THIRD SUB-CELL LDY LN9 LDA LN9+1 LDX 6 ;SET UP TO CLEAR THE LAST SUB-CELL CLRSUB: ;CLEAR SUB-CELLS. ; X NUMBER OF SUB-CELLS TO CLEAR. ; Y ADDRESS OF BEGINNING OF CLEARING, LOW ; ACC ADDRESS OF BEGINNING OF CLEARING, HIGH ;DO THE CLEARING BY CREATING THREE POINTERS ON PAGE 00 TO THE SCREEN: ;0,1 PTR TO TOP RASTER LINE IN SUB-CELL ;2,3 PTR TO MIDDLE RASTER LINE ;4,5 PTR TO BOTTOM RASTER LINE STA 1 ;SET UP HIGH POINTERS TO TOP, CLC ADC #20H ;(LEAVES CARRY CLEAR) STA 3 ; MIDDLE, AND ADC #20H ;(LEAVES CARRY CLEAR) STA 5 ; BOTTOM RASTER LINES OF SUB-CELL ;TEMPORARILY SET ATTRIBUTES TO ALL OFF SO SCREEN IS CLEARED TO NORMAL ; SPACES. SEI ;DISABLE INTERRUPTS LDA ATTRIB PHA ;SAVE ACC ON STACK AND #70H ;STRIP ATTRIBUTES EXCEPT FOR SCREEN BRIGHTNESS ORA #04H ;TAKE ATTRIBUTE FROM LATCH STA ATTRIB ;SAVE IN SOFTWARE STA ATT ;TELL HARDWARE CLI ;RE-ENABLE INTERRUPTS LDA #0 STA 0 STA 2 STA 4 ;BOTH LOW AND HIGH PARTS OF POINTERS NOW SET CLS1: STA (0),Y ;CLEAR TOP RASTER LINE OF THE SUB-CELL STA (2),Y ;CLEAR MIDDLE RASTER LINE OF THE SUB-CELL STA (4),Y ;CLEAR BOTTOM RASTER LINE OF THE SUB-CELL INY ;GO TO NEXT SUB-CELL HORIZONTALLY BNE CLS2 ;DIDN'T FALL OFF END OF MEMORY, CONTINUE INC 1 ;ADVANCE MOST SIG BYTE OF ADDRESS PTR TO SUB-CELLS INC 3 INC 5 BPL CLS2 ;CONTINUE IF THE 7X00H PART HASN'T INCREMENTED TO 8000H LDA #60H ;DO WRAP AROUND STA 5 ;PUT 6000H INTO 4,5 LDA #40H STA 3 ;4000H INTO 2,3 LSR A ;CONVERT 40H TO 20H STA 1 ;2000H INTO 0,1 TYA ;ACC = 00 CLS2: DEX ;HAVE ALL SUB-CELLS BEEN CLEARED? BNE CLS1 ;NO, CONTINUE PLA ;OTHERWISE, RESTORE SAVED ATTRIB AND #7FH ;ISOLATE LEAST SIGNIFICANT 7 BITS STA SCRATCH ;SAVE IN 'SCRATCH' IN ZERO PAGE RAM SEI ;DISABLE INTERRUPTS LDA ATTRIB ;GET ATTRIBUTE BYTE AND #80H ;ISOLATE SOFTWARE BLINK BIT ORA SCRATCH ;COMBINE WITH ATTRIBUTE BYTE STA ATTRIB ;STORE BACK IN ATTRIB STA ATT ;TELL HARDWARE CLI ;RE-ENABLE INTERRUPTS CLS3: RTS PAGE MOVSUB: ;MOVE 80 SUB-CELLS TO A DIFFERENT AREA. ;INPUT POINTERS ON PAGE ZERO: ; 0,1 TOP RASTER LINE OF SOURCE SUB-CELL ; 2,3 MIDDLE RASTER LINE ; 4,5 BOTTOM RASTER LINE ; 6,7 TOP RASTER LINE OF DESTINATION SUB-CELL ; 8,9 MIDDLE RASTER LINE ; 10,11 BOTTOM RASTER LINE LDY #80 ;MOVE 80 SUB-CELLS, A WHOLE LINE LDX #0 MVSB1: LDA (0,X) STA (6,X) ;MOVE TOP, LDA (2,X) STA (8,X) ; MIDDLE, LDA (4,X) STA (10,X) ; AND BOTTOM BYTES INC 0 INC 2 INC 4 ;INCREMENT LOW SOURCE POINTERS BNE MVSB2 ;NO OVERFLOW, CONTINUE INC 1 INC 3 INC 5 ;INCREMENT HIGH SOURCE POINTERS BPL MVSB2 ;NO WRAP, CONTINUE LDA #60H STA 5 ;WRAP BOTTOM TO 6000H, LDA #40H STA 3 ; MIDDLE TO 4000H, LSR A STA 1 ; AND TOP TO 2000H MVSB2: INC 6 INC 8 INC 10 ;INCREMENT LOW DESTINATION POINTERS BNE MVSB3 ;NO OVERFLOW, CONTINUE INC 7 INC 9 INC 11 ;INCREMENT HIGH SOURCE POINTERS BPL MVSB3 ;NO WRAP, CONTINUE LDA #60H STA 11 ;WRAP BOTTOM TO 6000H, LDA #40H STA 9 ; MIDDLE TO 4000H, LSR A STA 7 ; AND TOP TO 2000H MVSB3: DEY ;MORE SUB-CELLS? BNE MVSB1 ;YES, CONTINUE RTS PAGE DOLN: ;COMPUTE THE LN0 THROUGH LN11 VARIABLES GIVEN HCUR, VCUR, AND ; THE HARDWARE HOME ADDRESS IN CRTC REGISTERS 12 AND 13. ;DO THE COMPUTATION ONLY IF THE LNOK VARIABLE IS ZERO. LDY LNOK ;ALREADY OK? BNE CLS3 ;YES, DONE DOLN1: PHA ;SAVE ACC ;FIRST COMPUTE THE ADDRESS OF THE TOP RASTER LINE OF THE CURSOR. LDY VCUR ;Y = CURSOR'S LINE NUMBER LDA CRTCRG13 ;ACC = CRTC HOME ADDRESS LOW CLC ADC LOLINTBL,Y ;ACC = CRTC HOME ADDRESS LOW + OFFSET TO CURSOR LINE TAX ;X = CURSOR LINE ADDRESS LOW LDA CRTCRG12 ;ACC = CRTC HOME ADDRESS HIGH ADC HILINTBL,Y ;ACC = CRTC HOME ADDRESS HIGH + OFFSET TO CURSOR LINE + ; CARRY (LEAVES CARRY CLEAR) STA LNOK ;SET THE LNOK FLAG SO WE WON'T COMPUTE AGAIN ; (ACC MUST BE 2000H-3FFFH OR MAYBE 40XX) ;ALSO, LNOK IS USED AS A TEMP VARIABLE FOR THIS VALUE ;AT THIS POINT, LNOK,X HOLD THE CURSOR LINE ADDRESS. IT MIGHT BE ; GREATER THAN 3FFFH BUT IT IS UNNECESSARY TO WRAP IT AROUND TO 2000H ; NOW SINCE IT WILL BE DONE SHORTLY. ;ADD THE CURSOR HORIZONTAL OFFSET TO GET THE CURSOR ADDRESS. TXA ADC HCUR ;ACC = CURSOR ADDRESS LOW ;SET UP THE ADDRESSES FOR THE FIRST SUB-CELL. STA LN0 STA LN1 STA LN2 ;ALL LOW BYTES ARE THE SAME LDA LNOK ;ACC = CURSOR LINE ADDRESS HIGH ADC #0 ;ADD CARRY FROM ADDITION OF CURSOR HORIZONTAL OFFSET ;(LEAVES CARRY CLEAR) AND #1FH ORA #20H ;WRAP 3FFFH AROUND TO 2000H STA LN0+1 ;HIGH BYTES START AT 2000H, ADC #20H ;(LEAVES CARRY CLEAR) STA LN1+1 ; 4000H, ADC #20H ;(LEAVES CARRY CLEAR) STA LN2+1 ; AND 6000H ;SET UP THE ADDRESSES FOR THE SECOND SUB-CELL. LDA LN0 ADC #80 ;THIS SUB-CELL STARTS 80 AFTER THE PREVIOUS STA LN3 STA LN4 STA LN5 ;ALL LOW BYTES ARE THE SAME LDA LN0+1 ADC #0 ;ADD CARRY (LEAVES CARRY LOW) AND #1FH ORA #20H ;WRAP 3FFFH AROUND TO 2000H STA LN3+1 ;HIGH BYTES START AT 2000H, ADC #20H ;(LEAVES CARRY CLEAR) STA LN4+1 ; 4000H, ADC #20H ;(LEAVES CARRY CLEAR) STA LN5+1 ; AND 6000H ;SET UP THE ADDRESSES FOR THE THIRD SUB-CELL. LDA LN3 ADC #80 ;THIS SUB-CELL STARTS 80 AFTER THE PREVIOUS STA LN6 STA LN7 STA LN8 ;ALL LOW BYTES ARE THE SAME LDA LN3+1 ADC #0 ;ADD CARRY (LEAVES CARRY LOW) AND #1FH ORA #20H ;WRAP 3FFFH AROUND TO 2000H STA LN6+1 ;HIGH BYTES START AT 2000H, ADC #20H ;(LEAVES CARRY CLEAR) STA LN7+1 ; 4000H, ADC #20H ;(LEAVES CARRY CLEAR) STA LN8+1 ; AND 6000H ;SET UP THE ADDRESSES FOR THE LAST SUB-CELL. LDA LN6 ADC #80 ;THIS SUB-CELL STARTS 80 AFTER THE PREVIOUS STA LN9 STA LN10 STA LN11 ;ALL LOW BYTES ARE THE SAME LDA LN6+1 ADC #0 ;ADD CARRY (LEAVES CARRY LOW) AND #1FH ORA #20H ;WRAP 3FFFH AROUND TO 2000H STA LN9+1 ;HIGH BYTES START AT 2000H, ADC #20H ;(LEAVES CARRY CLEAR) STA LN10+1 ; 4000H, ADC #20H ;(LEAVES CARRY CLEAR) STA LN11+1 ; AND 6000H PLA ;RESTORE ACC GLNDUN: RTS PAGE NEWGCUR: ;MOVE THE CURSOR TO PAR0, PAR1 AND RESET THE TMPXYDOTS. ;PAR0 = X, PAR1 = Y. LDA XYDOTS STA TMPXYDOT ;LINE DRAWN FROM THIS NEW POINT WILL START AT THE ; FIRST BIT OF THE MASK LDX #3 NEWGC1: LDA CSIPR0,X ;COPY PAR0 AND PAR1 TO X AND Y STA X,X DEX BPL NEWGC1 JSR XYNG ;FORCE RE-COMPUTATION OF XY VARIABLES DOGLN: ;GIVEN A POINT SPECIFIED BY THE COORDINATES IN THE VARIABLES X, Y. ; COMPUTE: ; XYADDR = THE ADDRESS OF THE BYTE CONTAINING THE POINT ; XYMASK = AN 8-BIT MASK WITH THE BIT ON CORRESPONDING TO XY ;DON'T BOTHER WITH COMPUTATION IF THE VALUES HAVE ALREADY BEEN FOUND. LDA XYOK ;NEED RE-COMPUTATION? BNE GLNDUN ;NO, DONE ;COMPUTE X/8, THE BYTE OFFSET FROM THE BEGINNING OF THE LINE. ;AT THE SAME TIME, CHECK IF X COORDINATE IS TOO LARGE. LDA X+1 ;ACC = X HIGH = X/256 LSR A STA XYADDR ;TEMP = X/512 LDA X ;ACC = X LOW ROR A ;X HAS NOW BEEN DIVIDED BY 2, DOUBLE PRECISION LSR XYADDR ;TEMP = X/1024 BNE NOPLOT ;IF NOT ZERO, X IS 1024 OR MORE, DON'T PLOT ROR A ;X HAS NOW BEEN DIVIDED BY 4, DOUBLE PRECISION ;FROM THIS POINT ON, WE CAN DEAL WITH SINGLE PRECISION ONLY FOR X. CMP #640/4 ;WAS X GREATER THAN 639? BCS NOPLOT ;YES, DON'T PLOT LSR A ;X HAS NOW BEEN DIVIDED BY 8 TAX ;REG X = BYTE OFFSET ON RASTER LINE ;CHECK IF Y COORDINATE IS NOT TOO LARGE. LDA Y ;ACC = Y LOW LDY Y+1 ;REG Y = Y/256 = Y HIGH BEQ DOGLN1 ;Y IS 255 OR LESS, NO NEED TO CHECK FURTHER DEY BNE NOPLOT ;IF NOT ZERO, Y IS 512 OR MORE, DON'T PLOT INY ;REG Y = Y HIGH CMP #LOW 300 ;WAS Y GREATER THAN 299? BCS NOPLOT ;YES, DON'T PLOT DOGLN1: ;ACC = Y LOW, REG Y = Y HIGH ;MULTIPLY Y BY 2 FOR USE AS ON OFFSET IN THE GRAPHICS LINE TABLE. ASL A STA XYADDR ;TEMP = Y * 2 LOW TYA ROL A ;ACC = Y * 2 HIGH (LEAVES CARRY CLEAR) ;ADD OFFSET IN TABLE TO START ADDRESS OF TABLE, ASSUMED TO START ON ; A PAGE BOUNDARY. ADC #HIGH GLNTBL STA XYADDR+1 ;TEMP+1 = Y * 2 HIGH ;AT THIS POINT, XYADDR TEMPORARILY HAS PTR TO GRAPHICS ; RASTER LINE TABLE STA XYOK ;SET FLAG SO NEXT TIME WE WON'T COMPUTE AGAIN ; (ACC MUST BE NON-ZERO HERE, I.E. GLNTBL OR HIGHER) ;ADD RASTER LINE OFFSET IN REG X TO GRAPHICS TABLE ENTRY TO ; GET TOTAL OFFSET FROM HOME ADDRESS. TXA LDY #0 ADC (XYADDR),Y ;ADD LOW BYTES TAX ;TEMP SAVE OFFSET INY ;ADVANCE Y TO READ HIGH PART OF TABLE ENTRY LDA (XYADDR),Y TAY ;REG Y = OFFSET TO BEG OF LINE HIGH ADC #0 ;ADD CARRY TO HIGH BYTE (LEAVES CARRY LOW) STA XYADDR+1 ;TEMP SAVE OFFSET HIGH ;NOW ADD THE TOTAL OFFSET TO THE HOME ADDRESS FROM THE CRTC. TXA ;ACC = OFFSET LOW ADC CRTCRG13 ;ADD CRTC HOME ADDRESS LOW STA XYADDR ;LOW NOW SETUP LDA XYADDR+1 ADC CRTCRG12 ;ADD HIGH BYTES AND #1FH ;STRIP OFF ALL BUT OFFSET WITHIN THE 2000H LONG BLOCK STA XYADDR+1 ;TEMP SAVE OFFSET TYA ;REG Y = OFFSET TO BEG OF LINE HIGH AND #0E0H ;STRIP OFF ALL BUT CORRECT 2000H LONG BLOCK ORA XYADDR+1 ;ACC = CORRECT HIGH ADDRESS STA XYADDR+1 ;XYADDR NOW SETUP ;COMPUTE THE BIT MASK. LDA X AND #07H ;STRIP ALL BUT THE BIT INFORMATION, I.E. X MOD 8 TAY LDA BITPAT,Y ;ACC = THE BIT MASK STA XYMASK ;MASK NOW SETUP RTS PAGE DOXSTEP:;STEP X BY -1, 0, OR +1 DEPENDING ON THE XSTEP. ;EITHER LEAVE THE XY VARIABLES CORRECTLY SET UP, OR CLEAR XYOK SO ; THEY'LL BE RE-COMPUTED. LDA XSTEP ;TEST STEP DIRECTION BEQ XYDONE ;ZERO, DON'T STEP AFTER ALL BMI DOXMI ;NEGATIVE, STEP TO THE LEFT ;XSTEP POSITIVE, STEP TO THE RIGHT. INC X BNE DOXPL1 ;NO OVERFLOW, CONTINUE INC X+1 DOXPL1: ;NOW FIX THE XYMASK LSR XYMASK ;THE BIT SHIFTS TO THE RIGHT BCC XYDONE ;STILL IN THE SAME BYTE, DONE ;SEE IF X IS NOW BEYOND 639. LDA X CMP #LOW 640 BEQ XYNG ;IF MATCH, MIGHT BE BEYOND SO RE-CALCULATE SINCE ; IT NEVER HURTS TO DO SO ;GO THE NEXT BYTE. LDA #80H STA XYMASK ;NEW MASK FOR NEXT BYTE INC XYADDR BEQ XYNG ;AT MEMORY PAGE BOUNDARIES, RE-COMPUTE BECAUSE OF ; THE POSSIBLE PROBLEMS WITH WRAPAROUND RTS NOPLOT: ;SET UP THE VARIABLES SO THAT A POINT PLOT WON'T HURT ANYTHING. LDA #0FFH STA XYADDR STA XYADDR+1 ;POINT TO PROM XYNG: LDA #0 STA XYOK ;FORCE RE-COMPUTATION XYDONE: RTS DOXMI: ;XSTEP NEGATIVE, STEP TO THE LEFT. LDA X BNE DOXMI1 ;WON'T BE UNDERFLOW, CONTINUE DEC X+1 DOXMI1: DEC X ;NOW FIX THE XYMASK ASL XYMASK ;THE BIT SHIFTS TO THE LEFT BCC XYDONE ;STILL IN THE SAME BYTE, DONE ;SEE IF X IS NOW LESS THAN 0. LDA X+1 BMI XYNG ;YES, FORCE RE-COMPUTATION ;GO THE PREVIOUS BYTE. LDA #01H STA XYMASK ;NEW MASK FOR PREVIOUS BYTE LDA XYADDR BEQ XYNG ;AT MEMORY PAGE BOUNDARIES, RE-COMPUTE BECAUSE OF ; THE POSSIBLE PROBLEMS WITH WRAPAROUND DEC XYADDR RTS PAGE DOYSTEP:;STEP Y BY -1, 0, OR +1 DEPENDING ON THE YSTEP. ;EITHER LEAVE THE XY VARIABLES CORRECTLY SET UP, OR CLEAR XYOK SO ; THEY'LL BE RE-COMPUTED. LDA YSTEP ;TEST STEP DIRECTION BEQ XYDONE ;ZERO, DON'T STEP AFTER ALL BMI DOYMI ;NEGATIVE, STEP UPWARDS ;YSTEP POSITIVE, STEP DOWNWARDS. INC Y BNE DOYPL1 ;NO OVERFLOW, CONTINUE INC Y+1 DOYPL1: ;SEE IF Y IS NOW BEYOND 299. LDA Y CMP #LOW 300 BEQ XYNG ;IF MATCH, MIGHT BE BEYOND SO RE-CALCULATE SINCE ; IT NEVER HURTS TO DO SO ;NOW UPDATE THE ADDRESS. LDA XYADDR+1 CLC ADC #20H ;JUST ADD 2000H TO THE ADDRESS TO GO TO THE NEXT LINE ; IN THE SAME SUB-CELL BMI XYNG ;IF SUB-CELL EXCEEDED, RE-COMPUTE STA XYADDR+1 RTS DOYMI: ;YSTEP NEGATIVE, STEP UPWARDS. LDA Y BNE DOYMI1 ;WON'T BE UNDERFLOW, CONTINUE DEC Y+1 DOYMI1: DEC Y ;SEE IF Y IS NOW LESS THAN 0. LDA Y+1 BMI XYNG ;YES, FORCE RE-COMPUTATION ;NOW UPDATE THE ADDRESS. LDA XYADDR+1 SEC SBC #20H ;JUST SUBTRACT 2000H FROM THE ADDRESS TO GO TO THE ; PREVIOUS LINE IN THE SAME SUB-CELL CMP #20H ;ADDRESS NOW LESS THAN 2000H? BCC XYNG ;YES, SUB-CELL EXCEEDED, RE-COMPUTE STA XYADDR+1 RTS PAGE POINT: ;PLOT A POINT AT (X,Y). ;DO THE PLOT OR NOT, DEPENDING ON THE NEXT BIT ROTATED IN TMPXYDOT. ; (THIS ALLOWS DOTTED, DASHED, DOT-DASHED, ETC.) ;IF IT IS DONE, DO A BIT SET, RESET, OR TOGGLE DEPENDING ON XYOPR. LDA TMPXYDOT ROL A ;CARRY = TMPXYDOT BIT 7 ROL TMPXYDOT ;CIRCULAR ROTATE TMPXYDOT LEFT BCC PDONE ;IF MOST SIG BIT OF ROTATED DOTS CLEAR, DON'T PLOT PNT: JSR DOGLN LDY #0 LDA XYMASK LDX XYOPR BEQ PSET ;XYOPR = 0, SET THE BIT BMI PTOG ;XYOPR NEGATIVE, TOGGLE THE BIT ;XYOPR POSITIVE, RESET THE BIT. EOR #0FFH ;INVERT THE MASK AND (XYADDR),Y ;"AND" IT WITH THE CURRENT SCREEN STA (XYADDR),Y ;WRITE NEW VALUE PDONE: RTS ;XYOPR ZERO, SET THE BIT. PSET: ORA (XYADDR),Y ;"OR" THE MASK WITH THE CURRENT SCREEN STA (XYADDR),Y ;WRITE THE NEW VALUE RTS ;XYOPR NEGATIVE, TOGGLE THE BIT. PTOG: EOR (XYADDR),Y ;"EOR" THE MASK WITH THE CURRENT SCREEN STA (XYADDR),Y ;WRITE THE NEW VALUE RTS PAGE XPLUSY: ;ADD MEMORY POINTED TO BY Y TO MEMORY POINTED TO BY X, STORE IN MEMORY ; POINTED TO BY X. DO THIS DOUBLE PRECISION. DON'T CHANGE XY. CLC LDA 0,X ADC 0,Y STA 0,X LDA 1,X ADC 1,Y STA 1,X RTS XMINUSY: ;SUBTRACT MEMORY POINTED TO BY X FROM MEMORY POINTED TO BY Y, STORE IN ; MEMORY POINTED TO BY X. DO THIS DOUBLE PRECISION. DON'T CHANGE XY. SEC LDA 0,X SBC 0,Y STA 0,X LDA 1,X SBC 1,Y STA 1,X RTS MOV2W: ;MOVE TWO WORDS FROM MEMORY POINTED TO BY Y TO MEMORY POINTED TO BY X. ; DON'T CHANGE XY. LDA 2,Y STA 2,X LDA 3,Y STA 3,X MOV1W: ;MOVE ONE WORD FROM MEMORY POINTED TO BY Y TO MEMORY POINTED TO BY X. ; DON'T CHANGE XY. LDA 0,Y STA 0,X LDA 1,Y STA 1,X RTS XMULT: ;MULTIPLY MEMORY WORD POINTED TO BY X BY THE NUMBER IN Y. ; DON'T CHANGE X. USE TEMPORARY VARIABLES 0, 1, 2. LDA 0,X STA 0 ORA 1,X BEQ RTS6 ;IF ORIGINAL NUMBER IS ZERO, FAST EXIT STY 2 ;SAVE THE NUMBER TO MULTIPLY BY LDA 1,X STA 1 ;COPY THE ORIGINAL NUMBER TO 0,1 LDY #0 STY 0,X STY 1,X ;CLEAR THE "ACCUMULATOR" XMLT1: JSR XPLUSY ;ADD THE ORIGINAL NUMBER TO THE "ACCUMULATOR" DEC 2 ; AS MANY TIMES AS SPECIFIED BNE XMLT1 RTS6: RTS DODX: ;"APPLY" THE XSTEP TO THE WORD POINTED TO BY X, I.E. IF XSTEP IS -1 ; THEN NEGATE THE WORD. LDA XSTEP ;TEST XSTEP BPL RTS5 ;XTEP IS +1, LEAVE THE WORD ALONE ;ELSE, -1, NEGATE THE WORD XNEG: LDA #0 SEC SBC 0,X STA 0,X LDA #0 SBC 1,X STA 1,X RTS5: RTS DODY: ;"APPLY" THE YSTEP TO THE WORD POINTED TO BY X, AS ABOVE. LDA YSTEP ;TEST YSTEP BMI XNEG ;YSTEP IS -1, NEGATE THE WORD RTS ;YSTEP IS +1, LEAVE THE WORD ALONE QUADRNT: ;COMPUTE THE QUADRANT IN WHICH (X1,Y1) RESIDES, ASSUMING THAT A ; COUNTER-CLOCKWISE ARC IS TO BE DRAWN. ; Y ; ^ QUADRANT ACC ON OUTPUT ; II ! I I 0 ; ! II 1 ; -----------------> X III 2 ; ! IV 3 ; III ! IV AT THE CENTER -1 ; ! LDA X1+1 ;SENSE SIGN OF X1 BMI QDR1 ;MINUS, MUST BE II OR III ORA X1 ;SENSE IF X1 = 0 BEQ QDR2 ;X1 = 0, MUST BE IV, II, OR ERROR ;ELSE, X1 IS POSITIVE, MUST BE I OR IV LDA Y1+1 ;SENSE SIGN OF Y1 BMI QIV ;MINUS, QUADRANT IV LDA #0 ;Y1 IS ZERO OR POSITIVE, QUADRANT I RTS QIV: LDA #3 RTS QDR1: LDA Y1+1 ;SENSE SIGN OF Y1 BMI QIII ;MINUS, QUADRANT III ORA Y1 ;SENSE IF Y1 = 0 BEQ QIII ;Y1 = 0, QUADRANT III QII: LDA #1 ;QUADRANT II RTS QIII: LDA #2 RTS QDR2: LDA Y1+1 ;SENSE SIGN OF Y1 BMI QIV ;MINUS, QUADRANT IV ORA Y1 ;SENSE IF Y1 = 0 BNE QII ;Y1 IS POSITIVE, QUADRANT II LDA #-1 ;BOTH X1 AND Y1 ARE 0, ERROR RTS DIFFS: ;COMPUTE ALL FIRST AND SECOND ORDER DIFFERENTIALS FOR THE DDA ALGORITHM. ; RETURN S = TRUE IF UNTENABLE (X1,Y1), I.E. AT THE CENTER. ;DETERMINE THE QUADRANT THAT (X1,Y1) IS IN AND SET X AND Y STEPS ; AND DELTAS, AS APPROPRIATE. JSR QUADRNT BMI RTS5 STA QUAD ;SAVE THE CURRENT QUADRANT TAX ;X = THE QUADRANT, 0 TO 3 LDA QSTEPX,X ;READ CORRESPONDING XSTEP FROM TABLE STA XSTEP ;X STEP SET TO +1 OR -1 AS A BYTE STA XDELTA BMI ARC2A LDA #0 ARC2A: STA XDELTA+1 ;X DELTA SET TO +1 OR -1 AS A WORD LDA QSTEPY,X ;SAME FOR YSTEP STA YSTEP STA YDELTA BMI ARC2B LDA #0 ARC2B: STA YDELTA+1 ;INITIALIZE THE DIFFERENTIALS FOR THE DDA ALGORITHM. ;FIRST THE SECOND ORDER TERMS. LDY #BSQ LDX #DDZX JSR MOV2W ;DDZ(X) = B SQUARED, DDZ(Y) = A SQUARED JSR XPLUSY ;DDZX = 2 (B*B) LDY #ASQ LDX #DDZY JSR XPLUSY ;DDZY = 2 (A*A) ;NOW (PARTIALLY) THE FIRST ORDER TRIAL TERMS. LDY #X1 LDX #DZTX JSR MOV2W ;DZT(X) = X, DZT(Y) = Y LDY BSQ ;REG Y = B SQUARED JSR XMULT ;DZT(X) = (B*B) X LDY #2 ;MULTIPLING FACTOR OF 2 JSR XMULT ;DZT(X) = 2 (B*B) X JSR DODX ;DZT(X) = (B*B) X DX LDY ASQ ;REG Y = A SQUARED LDX #DZTY JSR XMULT ;DZT(Y) = (A*A) Y LDY #2 ;MULTIPLING FACTOR OF 2 JSR XMULT ;DZT(Y) = 2 (A*A) Y JSR DODY ;DZT(Y) = (A*A) Y DY ; AND THE FIRST ORDER NORMAL TERMS. LDY #DZTX LDX #DZX JSR MOV2W ;DZ(X) = 2 (B*B) X DX, DZ(Y) = 2 (A*A) Y DY LDY #BSQ JSR XPLUSY ;DZ(X) = 2 (B*B) X DX + (B*B) LDX #DZY LDY #ASQ JSR XPLUSY ;DZ(Y) = 2 (A*A) Y DY + (A*A) ;NOW COMPLETE THE FIRST ORDER NORMAL TERMS. LDY #BSQ LDX #0 JSR MOV2W ;0,1 = (B*B) 2,3 = (A*A) LSR 1 ROR 0 LSR 1 ROR 0 ;0,1 = (B*B)/4 LSR 3 ROR 2 LSR 3 ROR 2 ;2,3 = (A*A)/4 LDY #0 LDX #DZTX JSR XPLUSY ;DZT(X) = (B*B) X DX + (B*B)/4 LDY #2 LDX #DZTY JSR XPLUSY ;DZT(Y) = (A*A) Y DY + (A*A)/4 LDA #1 RTS ;RETURN S = FALSE XX: ;PLOT THE POINT (X1,Y1). DETERMINE IF THIS POINT IS AT THE END POINT ; AND RETURN Z = TRUE IF SO. IF NOT, UNCONDITIONALLY STEP X AND ; CONDITIONALLY STEP Y. RETURN Z FALSE. JSR POINT ;PLOT A POINT LDA QUAD CMP ENDQUAD ;ARE WE IN THE END POINT'S QUADRANT? BNE XX1 ;NO, CONTINUE LDA X1 CMP CSIPR3 BNE XX1 LDA X1+1 CMP CSIPR3+1 BNE XX1 RTS XX1: ;STEP X1 BY DELTA X, Z BY DZX, DZX AND DZTX BY DDZX, AND X BY X STEP. JSR YY3 ;SEE IF WE MUST STEP Y1 BY SEEING IF A Y1 STEP OF 1/2 WOULD GO TO THE ; OTHER SIDE OF THE CIRCLE. LDA Z+1 EOR DZY+1 BPL XX2 ;IF Z AND DZY HAVE THE SAME SIGN, THEN STEPPING Y1 ; CAN NEVER HELP LDA Z CLC ADC DZTY LDA Z+1 ADC DZTY+1 EOR Z+1 BMI XX2 ;IF Z + DZTY CHANGES SIGN THEN DON'T DO Y1 STEP ;STEP Y1 BY DELTA Y, Z BY DZY, DZY AND DZTY BY DDZY, AND Y BY Y STEP. XX3: LDY #YDELTA LDX #Y1 JSR XPLUSY LDY #DZY LDX #Z JSR XPLUSY LDY #DDZY LDX #DZY JSR XPLUSY LDX #DZTY JSR XPLUSY JSR DOYSTEP XX2: LDA #1 RTS ;RETURN Z FALSE YY: ;PLOT THE POINT (X1,Y1). DETERMINE IF THIS POINT IS AT THE END POINT ; AND RETURN Z = TRUE IF SO. IF NOT, UNCONDITIONALLY STEP Y AND ; CONDITIONALLY STEP X. RETURN Z FALSE. JSR POINT ;PLOT A POINT LDA QUAD CMP ENDQUAD ;ARE WE IN THE END POINT'S QUADRANT? BNE YY1 ;NO, CONTINUE LDA Y1 CMP CSIPR4 BNE YY1 LDA Y1+1 CMP CSIPR4+1 BNE YY1 RTS YY1: ;STEP Y1 BY DELTA Y, Z BY DZY, DZY AND DZTY BY DDZY, AND Y BY Y STEP. JSR XX3 ;SEE IF WE MUST STEP X1 BY SEEING IF A X1 STEP OF 1/2 WOULD GO TO THE ; OTHER SIDE OF THE CIRCLE. LDA Z+1 EOR DZX+1 BPL YY2 ;IF Z AND DZX HAVE THE SAME SIGN, THEN STEPPING X1 ; CAN NEVER HELP LDA Z CLC ADC DZTX LDA Z+1 ADC DZTX+1 EOR Z+1 BMI YY2 ;IF Z + DZTX CHANGES SIGN THEN DON'T DO X1 STEP ;STEP X1 BY DELTA X, Z BY DZX, DZX AND DZTX BY DDZX, AND X BY X STEP. YY3: LDY #XDELTA LDX #X1 JSR XPLUSY LDY #DZX LDX #Z JSR XPLUSY LDY #DDZX LDX #DZX JSR XPLUSY LDX #DZTX JSR XPLUSY JSR DOXSTEP YY2: LDA #1 RTS7: RTS ;RETURN Z FALSE TRANS: ;DETECT A TRANSITION FROM STEPPING X OR Y TO STEPPING THE OTHER WHEN ; WE REACH 45 DEGREES, I.E. WHEN DZX + DZY IS NO LONGER NEGATIVE. ; THIS CRITERION IS CORRECT IN ALL QUADRANTS. LDA DZX CLC ADC DZY LDA DZX+1 ADC DZY+1 BMI RTS7 ;IF DZX + DZY < 0, CONTINUE IN LOOP BY EXITING ; WITH MINUS TRUE ;WE ARE AT THE TRANSITION POINT. SEE IF THE END POINT IS OUTSIDE THE ; CIRCLE AND WILL NEVER BE HIT ON THE NEXT OCTANT. IF SO, RETURN Z ; TRUE. ;TO DO THIS, DETERMINE THE END POINT RELATIVE TO THE CURRENT POINT. LDY #X1 LDX #4 JSR MOV2W ;TEMP SAVE (X1,Y1) LDY #CSIPR3 LDX #X1 JSR XMINUSY JSR XNEG LDY #CSIPR4 LDX #Y1 JSR XMINUSY JSR XNEG JSR QUADRNT ;ACC =QUADRANT OF END POINT RELATIVE TO (X1,Y1) BMI TRS1 ;END POINT RIGHT AT THE TRANSITION, DONE, EXIT Z TRUE CMP QUAD ;IS IT THE SAME AS THE CURRENT QUADRANT? BEQ TRS1 ;YES, STOP RIGHT HERE, EXIT Z TRUE LDY #4 LDX #X1 JSR MOV2W ;RESTORE (X1,Y1) LDA #1 RTS ;EXIT S AND Z FALSE TRS1: LDA #0 ;EXIT Z TRUE RTS PAGE ;>>>>>>> I N T E R R U P T S E R V I C E R O U T I N E <<<<<<< INT: STA RTC ;RESET SOURCE OF INTERRUPT INC CLKTICK ;INCREMENT CLOCK TICK VARIABLE ; THIS AFFECTS CONDITION FLAGS, BUT THEY'RE SAVED BY ; THE HARDWARE DURING AN INTERRUPT ;COPY THE SOFTWARE HOME ADDRESS TO THE HARDWARE HOME ADDRESS. PHA ;SAVE ACC REGISTER TYA ;MOVE Y REG TO ACC PHA ;SAVE Y REGISTER TXA ;MOVE X REG TO ACC PHA ;SAVE X REGISTER SETCRT: LDA CRTCRG12 ;READ SOFTWARE HOME HIGH LDY CRTCRG13 ; AND LOW LDX #12 ;X = PTR TO CRTC HOME ADDRESS HIGH STX CRTCA ;SELECT IT INX ;X = PTR TO CRTC HOME ADDRESS LOW ;AS QUICKLY AS POSSIBLE, LOAD UP THE NEW HOME ADDRESS TO THE CRTC. ; THIS PRECAUTION MINIMIZES THE TIME DURING WHICH THE CRTC HARDWARE ; MIGHT READ THE HOME ADDRESS AND CATCH IT IN THE MIDDLE OF A CHANGE. STA CRTCD ;WRITE NEW VALUE HIGH STX CRTCA ;SELECT LOW ADDRESS STY CRTCD ;WRITE NEW VALUE LOW PLA ;GET SAVED X REGISTER TAX ;RESTORE X REGISTER PLA ;GET SAVED Y REGISTER TAY ;RESTORE Y REGISTER PLA ;RESTORE SAVED ACC DEC BLNKCTR ;DECREMENT BLINK COUNTER BEQ TOGGLE ;IF EXPIRED, THEN TOGGLE STATE RTI ;RETURN FROM INTERRUPT TOGGLE: PHA ;SAVE ACC REGISTER LDA ATTRIB ;GET CURRENT ATTRIB BYTE EOR #80H ;INVERT BIT 7 OF CURRENT ATTRIB STA ATTRIB ;RESTORE NEW ATTRIB BYTE STA ATT ;WRITE ATTRIB TO HARDWARE BMI TOGON ;GO LOAD COUNTER FOR 'ONTIME' IF BIT 7 = 1 LDA TIMEOFF ;OTHERWISE, GET 'OFFTIME' VALUE STA BLNKCTR ;STORE IN COUNTER PLA ;RESTORE ACC TO PREVIOUS VALUE RTI ;RETURN FROM INTERRUPT TOGON: LDA TIMEON ;GET 'ONTIME' COUNTER STA BLNKCTR ;STORE IN COUNTER PLA ;RESTORE ACC TO PREVIOUS VALUE RTI ;RETURN FROM INTERRUPT PAGE START: LDX #0FFH ;LOAD X REGISTER WITH 0FFH TXS ;LOAD STACK POINTER JSR INIT ;INITIALIZE DISPLAY HARDWARE LDA #FF ;LOAD UP A FORM FEED CHARACTER JMP DOIT ;JUMP AND DO IT ; ; INIT: ;HARDWARE INITIALIZATION. ;FIRST, DO INTERNAL HOUSEKEEPING. CLD ;SET BINARY MODE ;SET UP 8255A INTERFACE CHIP TO TALK WITH THE PROCESSING SECTION. LDA #0B4H ;MODE 1, PORT A INPUT, PORT B OUTPUT, PORT C HANDSHAKE STA IOCTRL ;SET UP THE HARDWARE LDA #0FH ;INDIVIDUALLY TURN ON PORT C, BIT 7 AND STA IOCTRL LDA #0DH ; BIT 6. THIS IS REQUIRED BY THE STA IOCTRL ; DISCIPLINE, WHICH LATER STROBES THEM LOW. LDA #09H STA IOCTRL ;ALSO SET PC4 AND LDA #05H STA IOCTRL ; PC2 ;COPY THE CURSOR MASK FROM PROM TO RAM. LDX #12-1 CURCPY: LDA CURSOR,X STA CURMSK,X DEX BPL CURCPY ;CREATE THE REVERSE MASK IN THE RAM. LDX #12-1 LDA #0FFH REVCRT: STA REVMSK,X DEX BPL REVCRT ;COPY THE CHARACTER FONT FROM PROM TO RAM SO IT CAN BE CHANGED. ;COPY 256 CHARS FROM THE PROM. LDY #0 ;Y = 00 STY 2 FNTL4: LDX #LOW CHARS STX 0 LDX #HIGH CHARS STX 1 ;0,1 = PTR TO SOURCE OF CHARS FNTL0: LDX #HIGH CGLN0 STX 3 ;2,3 = PTR TO DESTINATION OF CHARS FNTLUP: LDA (0),Y STA (2),Y ;COPY ONE BYTE OF THE FONT ;UPDATE THE SOURCE POINTER IN THE PROM. INC 0 ;GO TO NEXT BYTE IN PROM BNE FNTL2 ;IF NO OVERFLOW, CONTINUE INC 1 FNTL2: ;SOURCE POINTER NOW UPDATED ;UPDATE THE DESTINATION POINTER IN THE RAM. INC 3 ;STORE NEXT FONT BYTE ON NEXT PAGE LDA 3 ;WHAT PAGE ARE WE ON NOW? CMP #HIGH CGEND ;AFTER ALL THE CHARACTER FONT PAGES? BNE FNTLUP ;NO, CONTINUE INC 2 ;YES, DO THE NEXT CHARACTER BNE FNTL0 ;IF MORE CHARACTERS, CONTINUE ON FIRST PAGE (TOP BYTE) ;INITIALIZE THE ATTRIBUTES TO ALL OFF, BUT INTENSITY ATTRIBUTE IS BOLD. LDA #44H ; STA ATTRIB ;TELL THE SOFTWARE ; (HARDWARE WILL BE TOLD LATER BY THE XFF ROUTINE.) LDA #ONTIME ;GET DEFAULT 'ON TIME' VALUE STA TIMEON ;STORE AT 'TIMEON' IN RAM LDA #OFFTIME ;GET DEFAULT 'OFF TIME' VALUE STA TIMEOFF ;STORE AT 'TIMEOFF' IN RAM STA BLNKCTR ;STORE VALUE IN COUNTER ;INITIALIZE THE CONDITIONS. LDA #78H ;REPLACE MODE, BLINKING CURSOR, ; SLOW SCROLL, AUTO NEWLINE, UNDERLINE OFF STA CONDS LDY #0 ;Y = 00 STY SOFLG ;SET SHIFT IN MODE STY CURDSP ;CURSOR NOT CURRENTLY DISPLAYED STY CURBLK+2 ;INITIALIZE PHOSPHOR SAVER STY XYOPR ;DEFAULT GRAPHICS TO "OR" ON THE DOTS DEY ;Y = FFH STY XYDOTS STY TMPXYDOT ;DEFAULT GRAPHICS TO DRAW ALL DOTS LDA #(-20H) STA G0VAL ;USE FIRST 96 CHARS AS G0 SET LDA #(-20H) STA G1VAL ;USE FIRST 96 CHARS AS G1 SET LDA #60H ;OP CODE FOR RTS INSTRUCTION STA XUSER ;PLANT IT IN USER ESCAPE SEQUENCE TO ACT AS NO-OP LDA #00 STA LOGTOP ;DEFAULT VALUE FOR ADJUSTABLE SCROLLING REGION LDA #24 STA LOGBOT ;DEFAULT INSERT/DELETE TO DO ENTIRE SCREEN LDA #4CH ;OP CODE FOR JMP INSTRUCTION STA XINT ;PLANT IT IN INTERRUPT TABLE LDA #LOW INT STA XINT + 1 LDA #HIGH INT STA XINT + 2 ; SO INTERRUPTS JUMP TO INT CLI ;TURN ON INTERRUPTS LDA #48H STA KBDBYT ;KEYBOARD DEFAULTS TO US, CLICK AND AUTO-REPEAT ON. RTS ;RETURN FROM SUBROUTINE PAGE ;CHARACTER GENERATOR ;THE CHARACTERS ARE INTENDED TO BE DISPLAYED IN AN EIGHT WIDE BY TWELVE ; HIGH CELL. THE RASTER LINES IN THE CELL ARE ASSIGNED, BY ; CONVENTION, AS FOLLOWS: ; UPPER LOWER CASE HAS THREE VERSIONS ;LINE CASE NORMAL ASCNDR DESCENDER ;----- ----- ----- ----- ----- ; 0 THIS LINE IS RESERVED FOR ACCENTS ; 1 THIS LINE IS RESERVED FOR ACCENTS ; 2 * * ; 3 * * ; 4 * * * * ; 5 * * * * ; 6 * * * * ; 7 * * * * ; 8 * * * * ; 9 * ; 10 * THIS LINE ALSO HAS UNDERLINES ; 11 * ;EXAMPLES OF LOWER CASE WITH ASCENDERS: BDFHIKLT. ;EXAMPLES OF LOWER CASE WITH DESCENDERS: GJPQY. ;THE FIRST BYTE OF ALL CHARACTERS IS ASSUMED TO BE DESTINED FOR RASTER ; LINE 0. THE FOLLOWING ELEVEN BYTES ARE FOR THE REMAINING LINES. ;THE HEX CODES ARE GENERATED BY DRAWING THE CHARACTER, FOR EXAMPLE "E", ; ON GRAPH PAPER (OR USING THE FONTDB PROGRAM) AND THEN ASSIGNING ; THE PIXELS TO BITS AS FOLLOWS (BIT 7 IS NORMALLY BLANK): ; B7 B6 B5 B4 B3 B2 B1 B0 ; * * * * = HEX 3C ; * * = HEX 42 ; * * * * * * = HEX 7E ; * = HEX 40 ; * * * * = HEX 3C PAGE CHARS: ;THE FIRST 96 CHARS ARE THE NORMAL ASCII CHARACTERS. (G0 FONT) ;HEX 20 - 7F ;LINE 0 1 2 3 4 5 6 7 8 9 10 11 DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,020H,020H,020H,020H,020H,000H,020H,000H,000H,000H DB 000H,000H,024H,024H,024H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,024H,024H,07EH,024H,07EH,024H,024H,000H,000H,000H DB 000H,000H,010H,03CH,050H,038H,014H,078H,010H,000H,000H,000H DB 000H,000H,031H,032H,004H,008H,010H,026H,046H,000H,000H,000H DB 000H,000H,030H,048H,048H,030H,04AH,044H,03AH,000H,000H,000H DB 010H,020H,040H,000H,000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,004H,008H,010H,010H,010H,008H,004H,000H,000H,000H DB 000H,000H,020H,010H,008H,008H,008H,010H,020H,000H,000H,000H DB 000H,000H,000H,010H,054H,038H,054H,010H,000H,000H,000H,000H DB 000H,000H,000H,010H,010H,07CH,010H,010H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H,000H,030H,030H,010H,020H,000H DB 000H,000H,000H,000H,000H,07EH,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H,000H,030H,030H,000H,000H,000H DB 000H,000H,001H,002H,004H,008H,010H,020H,040H,000H,000H,000H DB 000H,000H,03CH,042H,046H,04AH,052H,062H,03CH,000H,000H,000H DB 000H,000H,008H,018H,028H,008H,008H,008H,07EH,000H,000H,000H DB 000H,000H,03CH,042H,004H,008H,010H,020H,07EH,000H,000H,000H DB 000H,000H,03CH,042H,002H,01CH,002H,042H,03CH,000H,000H,000H DB 000H,000H,040H,044H,044H,07EH,004H,004H,004H,000H,000H,000H DB 000H,000H,07EH,040H,07CH,002H,002H,042H,03CH,000H,000H,000H DB 000H,000H,03EH,040H,040H,07CH,042H,042H,03CH,000H,000H,000H DB 000H,000H,07EH,004H,008H,010H,020H,020H,020H,000H,000H,000H DB 000H,000H,03CH,042H,042H,03CH,042H,042H,03CH,000H,000H,000H DB 000H,000H,03CH,042H,042H,03EH,002H,002H,07CH,000H,000H,000H DB 000H,000H,000H,030H,030H,000H,000H,030H,030H,000H,000H,000H DB 000H,000H,000H,030H,030H,000H,000H,030H,030H,010H,020H,000H DB 000H,000H,004H,008H,010H,020H,010H,008H,004H,000H,000H,000H DB 000H,000H,000H,000H,07EH,000H,07EH,000H,000H,000H,000H,000H DB 000H,000H,020H,010H,008H,004H,008H,010H,020H,000H,000H,000H DB 000H,000H,03CH,042H,002H,004H,008H,000H,008H,000H,000H,000H DB 000H,000H,03CH,042H,04EH,052H,04CH,040H,03EH,000H,000H,000H DB 000H,000H,03CH,042H,042H,07EH,042H,042H,042H,000H,000H,000H DB 000H,000H,07CH,042H,042H,07CH,042H,042H,07CH,000H,000H,000H DB 000H,000H,03CH,042H,040H,040H,040H,042H,03CH,000H,000H,000H DB 000H,000H,078H,044H,042H,042H,042H,044H,078H,000H,000H,000H DB 000H,000H,07EH,040H,040H,078H,040H,040H,07EH,000H,000H,000H DB 000H,000H,07EH,040H,040H,078H,040H,040H,040H,000H,000H,000H DB 000H,000H,03CH,042H,040H,04EH,042H,042H,03CH,000H,000H,000H DB 000H,000H,042H,042H,042H,07EH,042H,042H,042H,000H,000H,000H DB 000H,000H,07CH,010H,010H,010H,010H,010H,07CH,000H,000H,000H DB 000H,000H,00FH,002H,002H,002H,002H,042H,03CH,000H,000H,000H DB 000H,000H,042H,044H,048H,050H,068H,044H,042H,000H,000H,000H DB 000H,000H,040H,040H,040H,040H,040H,040H,07EH,000H,000H,000H DB 000H,000H,042H,066H,05AH,042H,042H,042H,042H,000H,000H,000H DB 000H,000H,042H,062H,052H,04AH,046H,042H,042H,000H,000H,000H DB 000H,000H,03CH,042H,042H,042H,042H,042H,03CH,000H,000H,000H DB 000H,000H,07CH,042H,042H,07CH,040H,040H,040H,000H,000H,000H DB 000H,000H,03CH,042H,042H,042H,04AH,044H,03AH,000H,000H,000H DB 000H,000H,07CH,042H,042H,07CH,048H,044H,042H,000H,000H,000H DB 000H,000H,03CH,042H,040H,03CH,002H,042H,03CH,000H,000H,000H DB 000H,000H,07FH,008H,008H,008H,008H,008H,008H,000H,000H,000H DB 000H,000H,042H,042H,042H,042H,042H,042H,03CH,000H,000H,000H DB 000H,000H,042H,042H,042H,042H,044H,028H,010H,000H,000H,000H DB 000H,000H,042H,042H,042H,042H,05AH,066H,042H,000H,000H,000H DB 000H,000H,041H,022H,014H,008H,014H,022H,041H,000H,000H,000H DB 000H,000H,041H,022H,014H,008H,008H,008H,008H,000H,000H,000H DB 000H,000H,07FH,002H,004H,008H,010H,020H,07FH,000H,000H,000H DB 000H,000H,01CH,010H,010H,010H,010H,010H,01CH,000H,000H,000H DB 000H,000H,040H,020H,010H,008H,004H,002H,001H,000H,000H,000H DB 000H,000H,038H,008H,008H,008H,008H,008H,038H,000H,000H,000H DB 010H,028H,044H,000H,000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,0FFH,000H DB 010H,008H,004H,000H,000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,03CH,002H,03EH,042H,03EH,000H,000H,000H DB 000H,000H,040H,040H,05CH,062H,042H,062H,05CH,000H,000H,000H DB 000H,000H,000H,000H,03EH,040H,040H,040H,03EH,000H,000H,000H DB 000H,000H,002H,002H,03AH,046H,042H,046H,03AH,000H,000H,000H DB 000H,000H,000H,000H,03CH,042H,07EH,040H,03CH,000H,000H,000H DB 000H,000H,01CH,022H,020H,078H,020H,020H,020H,000H,000H,000H DB 000H,000H,000H,000H,03AH,044H,044H,038H,040H,03CH,042H,03CH DB 000H,000H,040H,040H,05CH,062H,042H,042H,042H,000H,000H,000H DB 000H,000H,008H,000H,018H,008H,008H,008H,01CH,000H,000H,000H DB 000H,000H,008H,000H,018H,008H,008H,008H,008H,008H,008H,070H DB 000H,000H,040H,040H,048H,050H,068H,044H,042H,000H,000H,000H DB 000H,000H,030H,010H,010H,010H,010H,010H,038H,000H,000H,000H DB 000H,000H,000H,000H,076H,049H,049H,049H,049H,000H,000H,000H DB 000H,000H,000H,000H,05CH,062H,042H,042H,042H,000H,000H,000H DB 000H,000H,000H,000H,03CH,042H,042H,042H,03CH,000H,000H,000H DB 000H,000H,000H,000H,05CH,062H,042H,062H,05CH,040H,040H,040H DB 000H,000H,000H,000H,03AH,046H,042H,046H,03AH,002H,002H,002H DB 000H,000H,000H,000H,05CH,062H,040H,040H,040H,000H,000H,000H DB 000H,000H,000H,000H,03EH,040H,03CH,002H,07CH,000H,000H,000H DB 000H,000H,010H,010H,07EH,010H,010H,010H,00EH,000H,000H,000H DB 000H,000H,000H,000H,042H,042H,042H,046H,03AH,000H,000H,000H DB 000H,000H,000H,000H,042H,042H,044H,028H,010H,000H,000H,000H DB 000H,000H,000H,000H,041H,049H,049H,049H,036H,000H,000H,000H DB 000H,000H,000H,000H,044H,028H,010H,028H,044H,000H,000H,000H DB 000H,000H,000H,000H,042H,042H,044H,028H,010H,020H,040H,080H DB 000H,000H,000H,000H,07CH,008H,010H,020H,07EH,000H,000H,000H DB 000H,000H,006H,008H,008H,030H,008H,008H,006H,000H,000H,000H DB 000H,000H,010H,010H,010H,000H,010H,010H,010H,000H,000H,000H DB 000H,000H,060H,010H,010H,00CH,010H,010H,060H,000H,000H,000H DB 032H,04CH,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,07EH,07EH,07EH,07EH,07EH,000H,000H,000H,000H PAGE ;THE NEXT 96 CHARACTERS ARE 32 SPECIAL SYMBOLS FOLLOWED BY 64 ; GARBAGE CHARACTERS. ; (G1 FONT) ORG CHARS + ( 96 * 12 ) ;LINE 0 1 2 3 4 5 6 7 8 9 10 11 DB 000H,000H,000H,000H,000H,000H,010H,000H,000H,000H,000H,000H DB 000H,000H,03FH,07AH,07AH,03AH,00AH,00AH,00AH,000H,000H,000H DB 000H,000H,010H,048H,024H,012H,024H,048H,010H,000H,000H,000H DB 000H,000H,008H,012H,024H,048H,024H,012H,008H,000H,000H,000H DB 000H,000H,07EH,040H,040H,070H,040H,04BH,04CH,008H,008H,000H DB 000H,000H,03CH,042H,042H,04CH,042H,052H,04CH,000H,000H,000H DB 000H,000H,001H,002H,004H,008H,050H,020H,000H,000H,000H,000H DB 000H,000H,018H,018H,018H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,010H,020H,07EH,020H,010H,000H,000H,000H,000H DB 000H,000H,000H,008H,004H,07EH,004H,008H,000H,000H,000H,000H DB 000H,000H,010H,010H,010H,010H,054H,038H,010H,000H,000H,000H DB 000H,000H,038H,040H,038H,044H,038H,004H,038H,000H,000H,000H DB 000H,000H,010H,038H,054H,010H,010H,010H,010H,000H,000H,000H DB 000H,000H,000H,000H,000H,004H,00CH,01CH,03CH,000H,000H,000H DB 000H,000H,018H,018H,000H,07EH,000H,018H,018H,000H,000H,000H DB 000H,000H,000H,07FH,008H,070H,010H,060H,000H,000H,000H,000H DB 038H,07CH,07CH,038H,000H,000H,000H,000H,000H,000H,000H,000H DB 038H,044H,044H,038H,000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,044H,038H,044H,044H,038H,044H,000H,000H,000H,000H DB 000H,000H,008H,03EH,048H,048H,048H,03EH,008H,000H,000H,000H DB 000H,000H,01CH,022H,020H,070H,020H,022H,07CH,000H,000H,000H DB 010H,07CH,010H,010H,010H,010H,010H,000H,000H,000H,000H,000H DB 010H,07CH,010H,010H,010H,07CH,010H,000H,000H,000H,000H,000H DB 000H,000H,010H,010H,07CH,010H,010H,000H,07CH,000H,000H,000H DB 038H,044H,07CH,044H,000H,000H,000H,000H,000H,000H,000H,000H DB 000H,040H,042H,044H,048H,050H,02CH,052H,004H,008H,01EH,000H DB 000H,040H,042H,044H,048H,052H,026H,04AH,01EH,002H,002H,000H DB 000H,000H,000H,000H,008H,014H,022H,07FH,000H,000H,000H,000H DB 024H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,03EH,040H,040H,040H,03EH,008H,030H,000H DB 000H,000H,004H,000H,004H,004H,004H,004H,004H,000H,000H,000H DB 000H,000H,010H,000H,010H,020H,040H,042H,03CH,000H,000H,000H PAGE ;THE NEXT 64 CHARACTERS ARE 64 GARBAGE CHARACTERS. ; (THIS IS WHERE THE POWER-UP-DIAGNOSTICS ARE PLACED) ; ;The purpose of this code is to do a hash total on the 6502 EPROM ; as a diagnostic tool during system boot-up. The range of ; the EPROM addresses is 0E000H to 0F000H. ; ; ; EQUATES ; ======= STRTAD EQU 0E000H ;START ADDRESS OF DBOOT ROM ENDADD EQU 0000H ;PROM END ADDRESS + 1 HSTART EQU 0 ;ZERO PAGE LOCATION FOR START ADDRESS HEND EQU 2 ;ZERO PAGE LOCATION FOR END ADDRESS HASH EQU 4 ;ZERO PAGE LOCATION FOR HASH ACCUMULATOR ; START OF CODE ; ============= ; ;CLEAR AND CHECK INTEGRITY OF MINIMAL RAM FOR OVERHEAD ; ; HASHTEST: ; ; SEI ;DISABLE EXTERNAL INTERRUPTS ; ; ;BLANK THE SCREEN... LDA #20H ;BIT TO BLANK SCREEN STA ATT ;TELL HARDWARE ;NOW SET UP THE CRT CONTROLLER CHIP SO STUFF WILL BE DISPLAYED. LDX #0 ;START WITH REGISTER 0 CRTINT: STX CRTCA ;SELECT IT LDA CRTTBL,X ;READ THE INITIALIZATION TABLE VALUE STA CRTCD ;OUTPUT IT INX ;GO TO THE NEXT REGISTER CPX #12 ;REGISTER 11 JUST OUTPUT? BNE CRTINT ;NO, CONTINUE ; ; LDY #04H ;# OF DATA PATTERNS TO TEST MORE: DEY ;POINT TO NEXT DATA PATTERN LDX #05H ;# OF RAM LOCATIONS TO CHECK AGAIN: DEX ;POINT TO NEXT LOCATION LDA DATA,Y ;GET DATA PATTERN TO CHECK STA 0,X ;STORE IN RAM CMP 0,X ;CHECK TO SEE IF STORED CORRECTLY BNE HERROR ;IF NOT, THEN RAM ERROR TXA ;GET X INDEX REGISTER INTO ACC BNE AGAIN ;IF NOT DONE, GO DO ANOTHER LOCATION TYA ;GET Y INDEX REGISTER INTO ACC BNE MORE ;IF NOT DONE WITH DATA PATTERNS, GO DO MORE ; ; ;START OF HASH TEST PROPER... ; ; LDA #LOW STRTAD ;GET LOW BYTE OF START ADDRESS STA HSTART ;...STORE IN ZERO PAGE RAM LDA #HIGH STRTAD ;GET HIGH BYTE OF START ADDRESS STA HSTART+1 ;...STORE IN ZERO PAGE RAM LDA #LOW ENDADD ;GET LOW BYTE OF END ADDRESS STA HEND ;...STORE IN ZERO PAGE RAM LDA #HIGH ENDADD ;GET HIGH BYTE OF END ADDRESS STA HEND+1 ;...STORE IN ZERO PAGE RAM LDA #0 ;LOAD ACC WITH ZERO STA HASH ;INIT HASH TOTAL TAX ;LOAD X REGISTER WITH ZERO CLC ;CLEAR CARRY BIT HLOOP: LDA (HSTART,X) ;LOAD BY INDIRECT INDEXED MODE (GET BYTE) ADC HASH ;ADD WITH CARRY STA HASH ;STORE SUM IN HASH INC HSTART ;INCREMENT STARTING ADDRESS (LO) BNE HSKIP ;IF NO WRAP AROUND, SKIP OVER INC HSTART+1 ;INCREMENT STARTING ADDRESS (HI) HSKIP: LDA HEND+1 ;GET END ADDRESS (HI) CMP HSTART+1 ;COMPARE WITH START ADDRESS (HI) BNE HLOOP ;IF DIFFERENT, NOT DONE...DO MORE LDA HEND ;GET END ADDRESS (LO) CMP HSTART ;COMPARE WITH START ADDRESS (LO) BNE HLOOP ;DIFFERENT ? THEN GO LOOP SOME MORE ; ; ;MAKE SURE THE HASH TOTAL IS CORRECT... ; ; LDA HASH ;IS HASH TOTAL CORRECT ? BNE HERROR ;NO... ERROR JMP RAMTEST ;YES...DONE, GO DO RAMTEST ; ; ;ERROR MESSAGE ROUTINE... ; ; HERROR: LDX #0FFH ;LOAD FF INTO X REGISTER TXS ;TRANSFER INDEX X TO STACK POINTER JSR INIT ;TRY TO INITIALIZE DISPLAY ; ; JSR XFF ;DO A FORM FEED ; ; LDY #0 ;LOAD Y REGISTER WITH ZERO HNCHAR: TYA ;MOVE Y REGISTER TO ACC PHA ;...SAVE ON STACK LDA HMSSG,Y ;GET MESSAGE BYTE CMP #'$' ;END OF STRING ? BEQ HHALT ;YES...ENTER INFINITE LOOP JSR DISP ;WRITE ONE CHARACTER TO SCREEN PLA ;GET SAVED Y REGISTER BACK TAY ;...MOVE BACK TO Y REGISTER INY ;POINT TO NEXT MESSAGE CHARACTER BYTE JMP HNCHAR ;ON TO NEXT CHARACTER ; ; HHALT: LDA #CRASHMD ;GET 8255 COMMAND BYTE STA IOCTRL ;SET UP 8255 (A=IN,B=OUT,C=IN) LDA #30H ;LOAD ASCII '0' STA IOPB ;SEND TO PORT B ; ; HHALT1: JMP HHALT1 ;INFINITE LOOP... ; ; ;---------------------------------------------------------------------- HMSSG: DB 'Failed EPROM hash total test. System halted.','$' ;---------------------------------------------------------------------- ; ; DATA: DB 0,55H,0AAH,0FFH ;DATA PATTERNS TO CHECK RAM ; ; HASHTOT: DB 00H ;THIS IS WHERE THE HASH TOTAL WILL GO ; ; PAGE ;This routine is used to fill a block of memory in the 6502's ; address space. It uses some memory in page 0 and the ; main routine can be located anywhere else. It fills the ; RAM with AA's, 55's, and 00's as a diagnostic test. ; Attribute ram is also checked with 10's, 01's and 00's. ; NOTE: ATTRIBUTE RAM IS LOCATED AT 2000H TO 7FFFH ONLY. ; ; ; EQUATES ; ======= CRASHMD EQU 99H ;8255 COMMAND BYTE ; ; STARTWO EQU 0020H ;START ADDRESS OF RAM TO CHECK (WITH OUT ATTRIBUTES) ENDADWO EQU 2000H ;END ADDRESS + 1 (WITH OUT ATTRIBUTES) STARTW EQU 2000H ;START ADDRESS (RAM WITH ATTRIBUTES) ENDADW EQU 8000H ;END ADDRESS + 1 (WITH ATTRIBUTES) OVRCNT EQU 20H ;OVER HEAD RAM COUNT ; ; STARTAD EQU 001BH ;RAM LOCATION FOR MEMORY POINTER TIMEOUT SET STARTAD+2 ;RAM LOCATION FOR TIMEOUT COUNTER ERRNUM SET TIMEOUT+2 ;RAM LOCATION FOR ERROR NUMBER ; ; ;CHECK A FEW RAM LOCATIONS TO BE USED FOR OVERHEAD (PAGE ZERO RAM)... ; ; ;ZERO OUT OVER HEAD RAM... (00H - 1FH) ; ; RAMTEST: LDX #OVRCNT ;# OF RAM LOCATIONS TO TEST LDZEROS: DEX ;ADJUST INDEX FOR NEXT BYTE LDA #0 ;VALUE TO STORE IN RAM STA 0,X ;STORE VALUE IN RAM TXA ;COPY X INDEX TO ACC BNE LDZEROS ;IF NOT DONE, DO MORE ; ; ;CHECK FOR ZEROS IN OVER HEAD RAM... ; ; LDX #OVRCNT ;# OF RAM LOCATIONS TO CHECK CHKZEROS: DEX ;ADJUST INDEX FOR NEXT BYTE LDA 0,X ;GET BYTE OF DATA FROM RAM BNE ERRVECT1 ;IF NOT ZERO, THEN ERROR TXA ;XFER X INDEX TO ACC BNE CHKZEROS ;IF NOT DONE, DO SOME MORE JMP NEXT ;CONTINUE TEST... ; ; ERRVECT1: ;>>> OVERHEAD RAM (00H-1FH) NOT ZEROED <<< LDA #31H ;LOAD ASCII '1' ERRVECT: STA ERRNUM ;SAVE IN RAM JMP ERROR ;GO TO ERROR ROUTINE ; ; ;RAM IS ZEROED... ; ; ;LOAD OVER HEAD RAM WITH DEFAULT VALUES AND CHECK RAM... ; ; NEXT: LDY #0 ;INDEX FOR DEFAULT VALUES LDX #OVRCNT ;# OF RAM LOCATIONS TO LOAD LOADMORE: DEX ;ADJUST INDEX FOR NEXT BYTE LDA VALUES,Y ;GET DEFAULT VALUE STA 0,X ;...AND PUT INTO RAM EOR #0FFH ;CHANGE VALUE IN ACC LDA 0,X ;READ BACK RAM LOCATION JUST LOADED CMP VALUES,Y ;COMPARE WITH VALUE JUST LOADED INTO RAM BNE ERRVECT2 ;IF DIFFERENT, THEN ERROR INY ;POINT TO NEXT DEFAULT VALUE TXA ;XFER X INDEX TO ACC BNE LOADMORE ;IF NOT DONE, DO SOME MORE BEQ BEGIN ;CONTINUE TEST... ; ; VALUES: DB 0,0,0 ;DUMMY VALUES DB (HIGH STARTWO),(LOW STARTWO) DB 0,0,0,0,0,0,0,0 ;DUMMY VALUES DB 0,0,0,0,0,0,0,0 ; " " DB 0,0,0,0,0,0,0,0 ; " " DB 0,0,0 ; " " ; ; ERRVECT2: ;>>> OVERHEAD RAM FAILURE (00H-1FH) IN WRITING DEFAULT VALUES <<< LDA #32H ;LOAD ASCII '2' JMP ERRVECT ;STORE AND EXIT ; ; ;RAM TEST PROPER... (20H - 1FFFH) ; ; BEGIN: LDX #0 ;INITIALIZE RAM INDEX POINTER LDY #0 ;INITIALIZE DATPAT INDEX POINTER ; ; ;FILL RAM WITH DATA PATTERN... ; ; FILLMORE: LDA DATPAT,Y ;GET DATA PATTERN TO CHECK STA (STARTAD,X) ;STORE DATPAT IN RAM INC STARTAD ;INCREMENT RAM ADDRESS (LO) BNE SKIP1 ;IF NO WRAP AROUND, SKIP OVER INC STARTAD+1 ;OTHERWISE, INCREMENT RAM ADDRESS (HI) SKIP1: LDA #HIGH ENDADWO ;GET END ADDRESS (HI) CMP STARTAD+1 ;ARE WE ON LAST PAGE OF RAM ? BNE FILLMORE ;NO, SO DO SOME MORE RAM FILL LDA #LOW ENDADWO ;GET END ADDRESS (LO) CMP STARTAD ;LAST ADDRESS OF CURRENT PAGE ? BNE FILLMORE ;NO, DO SOME MORE RAM FILL ; ; ;NOW CHECK THAT DATA WAS STORED CORRECTLY... ; ; CHECK: LDA #LOW STARTWO ;GET RAM START ADDRESS (LO) STA STARTAD ;...AND PUT INTO RAM POINTER LDA #HIGH STARTWO ;GET RAM START ADRRESS (HI) STA STARTAD+1 ;...AND PUT INTO RAM POINTER ALPHA: LDA (STARTAD,X) ;GET DATA BYTE FROM RAM CMP DATPAT,Y ;COMPARE WITH PATTERN THAT SHOULD BE THERE BNE ERRVECT3 ;NOT THERE, SO ERROR INC STARTAD ;INCREMENT START ADDRESS POINTER (LO) BNE SKIP2 ;IF NO WRAP AROUND, SKIP OVER NEXT INSTRUCTION INC STARTAD+1 ;INCREMENT START ADDRESS POINTER (HI) SKIP2: LDA #HIGH ENDADWO ;GET RAM END ADDRESS (HI) CMP STARTAD+1 ;COMPARE WITH RAM POINTER (HI) BNE ALPHA ;NOT ON LAST PAGE YET, SO CONTINUE AT 'ALPHA' LDA #LOW ENDADWO ;GET RAM END ADDRESS (LO) CMP STARTAD ;DONE WITH LAST LOCATION ON CURRENT PAGE ? BNE ALPHA ;NO, SO DO SOME MORE ; ; LDA #LOW STARTWO ;GET START ADDRESS (LO) STA STARTAD ;...AND STORE IN RAM POINTER LDA #HIGH STARTWO ;GET START ADDRESS (HI) STA STARTAD+1 ;...AND STORE IN RAM POINTER ; ; INY ;POINT TO NEXT DATA PATTERN TO CHECK CPY #2 ;LAST PATTERN DONE ? BNE FILLMORE ;NO, DO NEXT PATTERN BEQ WITHATTS ;CHECK RAM WITH ATTRIBUTES ; ; ERRVECT3: ;>>> RAM WITHOUT ATTRIBUTE RAM ERROR (20H-1FFFH) <<< LDA #33H ;LOAD ASCII '3' JMP ERRVECT ;STORE AND EXIT ; ; ;THIS IS WHERE RAM AND ATTRIBUTE RAM GETS TESTED.... (2000H - 7FFFH) ; ; WITHATTS: LDA #LOW STARTW ;GET RAM START ADDRESS (LO) STA STARTAD ;...AND PUT INTO RAM POINTER LDA #HIGH STARTW ;GET RAM START ADRRESS (HI) STA STARTAD+1 ;...AND PUT INTO RAM POINTER ; ; LDX #0 ;INITIALIZE RAM INDEX POINTER LDY #0 ;INITIALIZE DATPAT & ATTPAT INDEX POINTER ; ; ;LOAD ATTRIBUTE LATCH WITH ATTRIBUTE DATA... ; ; LOADATT: LDA ATTPAT,Y ;GET ATTRIBUTE DATA VALUE STA ATT ;LOAD ATTRIBUTE LATCH ; ; ;FILL RAM WITH DATA PATTERN... ; ; FILLWATT: LDA DATPAT,Y ;GET DATA PATTERN TO CHECK STA (STARTAD,X) ;STORE DATPAT IN RAM INC STARTAD ;INCREMENT RAM ADDRESS (LO) BNE SKIPWATT ;IF NO WRAP AROUND, SKIP OVER INC STARTAD+1 ;OTHERWISE, INCREMENT RAM ADDRESS (HI) SKIPWATT: LDA #HIGH ENDADW ;GET END ADDRESS (HI) CMP STARTAD+1 ;ARE WE ON LAST PAGE OF RAM ? BNE FILLWATT ;NO, SO DO SOME MORE RAM FILL LDA #LOW ENDADW ;GET END ADDRESS (LO) CMP STARTAD ;LAST ADDRESS OF CURRENT PAGE ? BNE FILLWATT ;NO, DO SOME MORE RAM FILL ; ; ;NOW CHECK THAT DATA WAS STORED CORRECTLY... ; ; LDA # %00100000 ;ENABLE STREAMING MODE (READ CURRENT ATTRIBUTE FROM RAM) STA ATT ;...SEND TO ATT LATCH ; ; CHKATT: LDA #LOW STARTW ;GET RAM START ADDRESS (LO) STA STARTAD ;...AND PUT INTO RAM POINTER LDA #HIGH STARTW ;GET RAM START ADRRESS (HI) STA STARTAD+1 ;...AND PUT INTO RAM POINTER ALPHATT: LDA (STARTAD,X) ;GET DATA BYTE FROM RAM CMP DATPAT,Y ;COMPARE WITH PATTERN THAT SHOULD BE THERE BNE ERRVECT4 ;NOT THERE, SO ERROR LDA ATT ;READ ATTRIBUTE RAM AND # %00000011 ;CLEAR ALL NON-RAM BITS ORA # %00100100 ;RESET EXTRA MODE BITS FOR COMPARE INSTRUCTION CMP ATTPAT,Y ;COMPARE WITH PATTERN THAT SHOULD BE THERE BNE ERRVECT5 ;IF NOT THERE, ERROR INC STARTAD ;INCREMENT START ADDRESS POINTER (LO) BNE SKIP2ATT ;IF NO WRAP AROUND, SKIP OVER NEXT INSTRUCTION INC STARTAD+1 ;INCREMENT START ADDRESS POINTER (HI) SKIP2ATT: LDA #HIGH ENDADW ;GET RAM END ADDRESS (HI) CMP STARTAD+1 ;COMPARE WITH RAM POINTER (HI) BNE ALPHATT ;NOT ON LAST PAGE YET, SO CONTINUE AT 'ALPHATT' LDA #LOW ENDADW ;GET RAM END ADDRESS (LO) CMP STARTAD ;DONE WITH LAST LOCATION ON CURRENT PAGE ? BNE ALPHATT ;NO, SO DO SOME MORE ; ; LDA #LOW STARTW ;GET START ADDRESS (LO) STA STARTAD ;...AND STORE IN RAM POINTER LDA #HIGH STARTW ;GET START ADDRESS (HI) STA STARTAD+1 ;...AND STORE IN RAM POINTER ; ; INY ;POINT TO NEXT DATA PATTERN TO CHECK CPY #2 ;LAST PATTERN DONE ? BNE LOADATT ;NO, DO NEXT PATTERN ; ; JMP NOTE ;TEST PASSED, CONTINUE ON... ; ; DATPAT: DB 0AAH,55H ATTPAT: DB %00100110,%00100101 ; ; ERRVECT4: ;>>> RAM PATTERN FAILURE (2000H-7FFFH) <<< LDA #34H ;LOAD ASCII '4' JMP ERRVECT ;STORE AND EXIT ERRVECT5: ;>>> ATTRIBUTE RAM PATTERN FAILURE (2000H-7FFFH) <<< LDA #35H ;LOAD ASCII '5' JMP ERRVECT ;STORE AND EXIT ; ; ;ERROR MESSAGE ROUTINE... ; ; ERROR: LDX #0FFH ;LOAD FF INTO X REGISTER TXS ;TRANSFER INDEX X TO STACK POINTER JSR INIT ;INITIALIZE THE DISPLAY ; ; JSR XFF ;DO A FORM FEED ; ; LDY #0 ;INITIALIZE Y INDEX TO ZERO RCHAR: TYA ;MOVE Y REGISTER TO ACC PHA ;...AND SAVE ON STACK LDA MSSG1,Y ;GET NEXT MESSAGE BYTE CMP #'$' ;TERMINATOR ? BEQ TELLNUM ;YES... INDICATE ERROR NUMBER JSR DISP ;DISPLAY THE CHARACTER PLA ;GET SAVED Y REGISTER TAY ;...AND PUT BACK INTO Y REGISTER INY ;INCREMENT MESSAGE INDEX POINTER JMP RCHAR ;LOOP AND DISPLAY THE NEXT CHARACTER ; ; ;---------------------------------------------------------------------- MSSG1: DB '6502 Memory Error. System Halted. ','$' ;---------------------------------------------------------------------- ; ; TELLNUM: PLA ;ADJUST STACK LDY #0 ;INITIALIZE Y INDEX TO ZERO TELLNUM1: TYA ;COPY Y INDEX TO ACC PHA ;...AND SAVE ON STACK LDA MSSG3,Y ;GET NEXT MESSAGE BYTE CMP #'$' ;TERMINATOR ? BEQ TELLNUM2 ;GO DISPLAY ACTUAL NUMBER JSR DISP ;DISPLAY MESSAGE CHARACTER PLA ;GET SAVED Y REGISTER TAY ;...AND PUT BACK INTO Y REGISTER INY ;INCREMENT INDEX POINTER JMP TELLNUM1 ;LOOP AND DISPALY NEXT CHARACTER ; ; ;---------------------------------------------------------------------- MSSG3: DB 'ERROR NUM: ','$' ;---------------------------------------------------------------------- ; ; TELLNUM2: PLA ;ADJUST STACK LDA ERRNUM ;GET ERROR NUMBER JSR DISP ;DISPLAY IT ; ; LDA #CRASHMD ;GET 8255 COMMAND BYTE STA IOCTRL ;SET UP 8255 (A=IN,B=OUT,C=IN) LDA ERRNUM ;LOAD ASCII ERROR NUMBER STA IOPB ;SEND TO PORT B ; ; HALT: JMP HALT ;INFINITE LOOP (HALT) ; ; NOTE: LDX #0FFH ;LOAD FF INTO X REGISTER TXS ;TRANSFER INDEX X TO STACK POINTER JSR INIT ;INITIALIZE THE DISPLAY ; ; JSR XFF ;DO A FORM FEED ; ; LDY #0 ;INITIALIZE Y INDEX TO ZERO RCHAR2: TYA ;COPY Y INDEX TO ACC PHA ;SAVE ON STACK LDA MSSG2,Y ;GET NEXT MESSAGE BYTE CMP #'$' ;TERMINATOR ? BEQ DONE ;YES... DONE JSR DISP ;IF NOT, DISPLAY THE CHARACTER PLA ;GET SAVED Y INDEX TAY ;...RESTORE Y INDEX INY ;INCREMENT MESSAGE INDEX JMP RCHAR2 ;LOOP AND DO THE NEXT CHARACTER ; ; ;---------------------------------------------------------------------- MSSG2: DB 'Self-Test in Progress. ','$' ;---------------------------------------------------------------------- ; ; DONE: LDA #0 ;LOAD UP A NULL CHARACTER JMP DOIT ;YES, TEST PASSED...JUMP TO NORMAL START OF IDLE LOOP ; ; DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM ; ; PAGE ;THESE ARE THE GRAPHIC CHARACTERS (020H THRU 03FH) (G2 FONT) ; ORG CHARS + (2 * 96 * 12) ; ; DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H ;020H DB 000H,000H,010H,038H,07CH,038H,010H,000H,000H,000H,000H,000H ;021H DB 000H,054H,028H,054H,028H,054H,028H,054H,000H,000H,000H,000H ;022H DB 000H,050H,050H,070H,05EH,054H,004H,004H,004H,000H,000H,000H ;023H DB 000H,078H,040H,070H,05EH,050H,01CH,010H,010H,000H,000H,000H ;024H DB 000H,078H,040H,040H,040H,07EH,012H,01EH,014H,012H,000H,000H ;025H DB 000H,040H,040H,040H,07EH,010H,01CH,010H,010H,000H,000H,000H ;026H DB 000H,018H,024H,024H,018H,000H,000H,000H,000H,000H,000H,000H ;027H DB 000H,010H,010H,07CH,010H,010H,000H,07CH,000H,000H,000H,000H ;028H DB 000H,048H,068H,058H,048H,008H,008H,00EH,000H,000H,000H,000H ;029H DB 000H,050H,050H,050H,05EH,024H,004H,004H,004H,000H,000H,000H ;02AH DB 010H,010H,010H,010H,010H,0F0H,000H,000H,000H,000H,000H,000H ;02BH DB 000H,000H,000H,000H,000H,0F0H,010H,010H,010H,010H,010H,010H ;02CH DB 000H,000H,000H,000H,000H,01FH,010H,010H,010H,010H,010H,010H ;02DH DB 010H,010H,010H,010H,010H,01FH,000H,000H,000H,000H,000H,000H ;02EH DB 010H,010H,010H,010H,010H,0FFH,010H,010H,010H,010H,010H,010H ;02FH DB 000H,0FFH,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H ;030H DB 000H,000H,000H,0FFH,000H,000H,000H,000H,000H,000H,000H,000H ;031H DB 000H,000H,000H,000H,000H,0FFH,000H,000H,000H,000H,000H,000H ;032H DB 000H,000H,000H,000H,000H,000H,000H,0FFH,000H,000H,000H,000H ;033H DB 000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,0FFH,000H ;034H DB 010H,010H,010H,010H,010H,01FH,010H,010H,010H,010H,010H,010H ;035H DB 010H,010H,010H,010H,010H,0F0H,010H,010H,010H,010H,010H,010H ;036H DB 010H,010H,010H,010H,010H,0FFH,000H,000H,000H,000H,000H,000H ;037H DB 000H,000H,000H,000H,000H,0FFH,010H,010H,010H,010H,010H,010H ;038H DB 010H,010H,010H,010H,010H,010H,010H,010H,010H,010H,010H,010H ;039H DB 000H,004H,008H,010H,020H,010H,008H,004H,07EH,000H,000H,000H ;03AH DB 000H,020H,010H,008H,004H,008H,010H,020H,07EH,000H,000H,000H ;03BH DB 000H,002H,07CH,024H,024H,024H,024H,024H,000H,000H,000H,000H ;03CH DB 000H,000H,000H,002H,004H,07EH,010H,07EH,040H,000H,000H,000H ;03DH DB 000H,000H,01CH,022H,020H,070H,020H,022H,07CH,000H,000H,000H ;03EH DB 000H,000H,000H,000H,000H,000H,010H,000H,000H,000H,000H,000H ;03FH ; ; ; THE NEXT 32 CHARACTERS ARE GARBAGE CHARACTERS... ; (THIS IS WHERE KEITH DAVISON'S ESCAPE SEQUENCES GO) ; ;SEND ONE SOFT CHARACTER - 12 BYTES, TOP TO BOTTOM. ; ESC > > 1 12-BYTES-OF-DATA. ; ; WRITE1: JSR WRTSUB ;WRITE A SOFT CHARACTER TO SCREEN JMP DISP2 ;FINISH UP CURSOR POSITIONING AND DO ; SOME ATTRIBUTE PROCESSING. ; ; ;WRITE A HORIZONTAL STRING OF SOFT CHARACTERS, 12 BYTES EACH, TOP TO BOTTOM. ; ESC > > H #-SOFT-CHARS THAT-BY-12-BYTES-OF-DATA ;0=256 BYTES ! ; ; WRITEH: JSR GETCHRY ;GET NUMBER OF SOFT CHARACTERS TO SEND STA SCRATCH ;SAVE IN TEMPORARY STORAGE WRITEHL: JSR WRTSUB ;WRITE A SOFT CHARACTER TO SCREEN JSR DISP2A+3 ; DEC SCRATCH ;DECREMENT CHARACTER COUNT BNE WRITEHL ;IF NOT DONE, DO SOME MORE RTS ;RETURN FROM SUBROUTINE ; ; ;WRITE A SOFT CHARACTER TO SCREEN ; ; WRTSUB: LDY #00 ;SET Y INDEX TO ZERO JSR GETCHRY ;GET TOP 8 BITS OF CHARACTER CELL STA (LN0),Y ;STORE IT JSR GETCHRY ;GET NEXT 8 BITS OF CHARACTER CELL STA (LN1),Y ;STORE IT JSR GETCHRY ;GET NEXT 8 BITS STA (LN2),Y ;STORE IT JSR GETCHRY ;...NEXT 8 BITS STA (LN3),Y ;STORE IT JSR GETCHRY ;...NEXT 8 BITS STA (LN4),Y ;STORE IT JSR GETCHRY ;...NEXT 8 BITS STA (LN5),Y ;STORE IT JSR GETCHRY ;...NEXT 8 BITS STA (LN6),Y ;STORE IT JSR GETCHRY ;...NEXT 8 BITS STA (LN7),Y ;STORE IT JSR GETCHRY ;...NEXT 8 BITS STA (LN8),Y ;STORE IT JSR GETCHRY ;...NEXT 8 BITS STA (LN9),Y ;STORE IT JSR GETCHRY ;...NEXT 8 BITS STA (LN10),Y ;STORE IT JSR GETCHRY ;BOTTOM 8 BITS STA (LN11),Y ;STORE IT RTS ;RETURN FROM SUBROUTINE ; ;'GETCHR' SUBROUTINE THAT SAVES THE Y INDEX... ; GETCHRY: TYA ;XFER Y INDEX TO ACC PHA ;SAVE ON STACK JSR GETCHR ;GET NEXT CHARACTER STA SCRATCH+3 ;SAVE CHARACTER IN TEMP RAM LOCATION PLA ;GET SAVED Y INDEX BACK TAY ;MOVE IT BACK TO Y INDEX LDA SCRATCH+3 ;MOVE SAVED CHARACTER BACK TO ACC RTS ;RETURN FROM SUBROUTINE ; ; ;DOWN LOAD AN INTEL HEX FORMAT FILE INTO USER RAM. ; ESC > : ; ; HEX: JSR GET2 ;GET DATA BYTE COUNT BEQ ABORT ;IF ZERO, THEN DONE TAY ;XFER DATA BYTE COUNT TO Y INDEX JSR GET2 ;GET LOAD ADDRESS, HIGH BYTE STA SCRATCH+1 ;SAVE IN RAM STORAGE JSR GET2 ;GET LOAD ADDRESS, LOW BYTE STA SCRATCH ;SAVE IN RAM STORAGE JSR GET2 ;GET "UNUSED BYTE" BNE ABORT ;IF NOT ZERO, THEN ERROR, SO ABORT HEXLOOP: JSR GET2 ;GET A DATA BYTE LDX #0 ;LOAD X INDEX WITH ZERO STA (SCRATCH,X) ;STORE DATA AT LOAD ADDRESS INC SCRATCH ;INCREMENT LOAD ADDRESS, LOW BYTE BNE CONT ;IF NO WRAP AROUND, CONTINUE AT 'CONT' INC SCRATCH+1 ;OTHERWISE, INCREMENT LOAD ADDRESS, HIGH BYTE CONT: DEY ;DECREMENT DATA BYTE COUNT BNE HEXLOOP ;IF NOT DONE, DO SOME MORE JSR GET2 ;FLUSH CHECK SUM BYTE ABORT: RTS ;RETURN FROM SUBROUTINE ; ; ;GET 2 ASCII CHARACTERS, CONVERT TO HEX ; ; GET2: JSR GETCHR ;GET AN ASCII CHARACTER JSR CONV ;CONVERT ASCII DATA TO HEX DATA ASL A ;ROTATE DATA ONE BIT LEFT ( X2 ) ASL A ; " " " " " ( X4 ) ASL A ; " " " " " ( X8 ) ASL A ;LOWER NIBBLE NOW UPPER NIBBLE ( X16 ) STA SCRATCH+2 ;SAVE IN TEMP STORAGE JSR GETCHR ;GET AN ASCII CHARACTER JSR CONV ;CONVERT ASCII DATA TO HEX DATA ORA SCRATCH+2 ;COMBINE UPPER & LOWER HEX NIBBLES RTS ;RETURN FROM SUBROUTINE ; ; ;CONVERT ONE HEX DIGIT TO NUMBER ; ; CONV: SEC ;PREPAER FOR A SUBTRACT SBC #30H ;SUBTRACT AN ASCII '0' CMP #11H ;WAS CHARACTER GREATER THAN ASCII '9' ? BCC CONVNUM ;NO, SO EXIT ROUTINE SEC ;YES, SO PREPARE TO SUBTRACT SBC #07H ;ADJUST ASCII 'A' THRU 'F' TO HEX CONVNUM: RTS ;RETURN FROM SUBROUTINE ; ; DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM DB 0,0,0,0,0,0,0,0 ;FILL IN EMPTY HOLES OF ROM ; ; PAGE ORG PROM + PROMLEN - 0300H ;THE TABLE MUST BEGIN ON A PAGE BOUNDARY GLNTBL: ;GRAPHICS RASTER LINE ADDRESS TABLE. ;THIS TABLE CONSISTS OF 300 ENTRIES, ONE FOR EACH RASTER LINE ON THE ; SCREEN. EACH ENTRY IS THE ABSOLUTE ADDRESS IN MEMORY OF THE ; CORRESPONDING RASTER LINE'S FIRST BYTE, ASSUMING THAT THE CRTC ; SCREEN HOME OFFSET IS 0000H. THE ACTUAL SCREEN HOME OFFSET IS THE ; SCREEN HOME ADDRESS FROM THE CRTC ANDED WITH 1FFFH. DW (0*80) +2000H DW (0*80) +4000H DW (0*80) +6000H DW (1*80) +2000H DW (1*80) +4000H DW (1*80) +6000H DW (2*80) +2000H DW (2*80) +4000H DW (2*80) +6000H DW (3*80) +2000H DW (3*80) +4000H DW (3*80) +6000H DW (4*80) +2000H DW (4*80) +4000H DW (4*80) +6000H DW (5*80) +2000H DW (5*80) +4000H DW (5*80) +6000H DW (6*80) +2000H DW (6*80) +4000H DW (6*80) +6000H DW (7*80) +2000H DW (7*80) +4000H DW (7*80) +6000H DW (8*80) +2000H DW (8*80) +4000H DW (8*80) +6000H DW (9*80) +2000H DW (9*80) +4000H DW (9*80) +6000H DW (10*80) +2000H DW (10*80) +4000H DW (10*80) +6000H DW (11*80) +2000H DW (11*80) +4000H DW (11*80) +6000H DW (12*80) +2000H DW (12*80) +4000H DW (12*80) +6000H DW (13*80) +2000H DW (13*80) +4000H DW (13*80) +6000H DW (14*80) +2000H DW (14*80) +4000H DW (14*80) +6000H DW (15*80) +2000H DW (15*80) +4000H DW (15*80) +6000H DW (16*80) +2000H DW (16*80) +4000H DW (16*80) +6000H DW (17*80) +2000H DW (17*80) +4000H DW (17*80) +6000H DW (18*80) +2000H DW (18*80) +4000H DW (18*80) +6000H DW (19*80) +2000H DW (19*80) +4000H DW (19*80) +6000H DW (20*80) +2000H DW (20*80) +4000H DW (20*80) +6000H DW (21*80) +2000H DW (21*80) +4000H DW (21*80) +6000H DW (22*80) +2000H DW (22*80) +4000H DW (22*80) +6000H DW (23*80) +2000H DW (23*80) +4000H DW (23*80) +6000H DW (24*80) +2000H DW (24*80) +4000H DW (24*80) +6000H DW (25*80) +2000H DW (25*80) +4000H DW (25*80) +6000H DW (26*80) +2000H DW (26*80) +4000H DW (26*80) +6000H DW (27*80) +2000H DW (27*80) +4000H DW (27*80) +6000H DW (28*80) +2000H DW (28*80) +4000H DW (28*80) +6000H DW (29*80) +2000H DW (29*80) +4000H DW (29*80) +6000H DW (30*80) +2000H DW (30*80) +4000H DW (30*80) +6000H DW (31*80) +2000H DW (31*80) +4000H DW (31*80) +6000H DW (32*80) +2000H DW (32*80) +4000H DW (32*80) +6000H DW (33*80) +2000H DW (33*80) +4000H DW (33*80) +6000H DW (34*80) +2000H DW (34*80) +4000H DW (34*80) +6000H DW (35*80) +2000H DW (35*80) +4000H DW (35*80) +6000H DW (36*80) +2000H DW (36*80) +4000H DW (36*80) +6000H DW (37*80) +2000H DW (37*80) +4000H DW (37*80) +6000H DW (38*80) +2000H DW (38*80) +4000H DW (38*80) +6000H DW (39*80) +2000H DW (39*80) +4000H DW (39*80) +6000H DW (40*80) +2000H DW (40*80) +4000H DW (40*80) +6000H DW (41*80) +2000H DW (41*80) +4000H DW (41*80) +6000H DW (42*80) +2000H DW (42*80) +4000H DW (42*80) +6000H DW (43*80) +2000H DW (43*80) +4000H DW (43*80) +6000H DW (44*80) +2000H DW (44*80) +4000H DW (44*80) +6000H DW (45*80) +2000H DW (45*80) +4000H DW (45*80) +6000H DW (46*80) +2000H DW (46*80) +4000H DW (46*80) +6000H DW (47*80) +2000H DW (47*80) +4000H DW (47*80) +6000H DW (48*80) +2000H DW (48*80) +4000H DW (48*80) +6000H DW (49*80) +2000H DW (49*80) +4000H DW (49*80) +6000H DW (50*80) +2000H DW (50*80) +4000H DW (50*80) +6000H DW (51*80) +2000H DW (51*80) +4000H DW (51*80) +6000H DW (52*80) +2000H DW (52*80) +4000H DW (52*80) +6000H DW (53*80) +2000H DW (53*80) +4000H DW (53*80) +6000H DW (54*80) +2000H DW (54*80) +4000H DW (54*80) +6000H DW (55*80) +2000H DW (55*80) +4000H DW (55*80) +6000H DW (56*80) +2000H DW (56*80) +4000H DW (56*80) +6000H DW (57*80) +2000H DW (57*80) +4000H DW (57*80) +6000H DW (58*80) +2000H DW (58*80) +4000H DW (58*80) +6000H DW (59*80) +2000H DW (59*80) +4000H DW (59*80) +6000H DW (60*80) +2000H DW (60*80) +4000H DW (60*80) +6000H DW (61*80) +2000H DW (61*80) +4000H DW (61*80) +6000H DW (62*80) +2000H DW (62*80) +4000H DW (62*80) +6000H DW (63*80) +2000H DW (63*80) +4000H DW (63*80) +6000H DW (64*80) +2000H DW (64*80) +4000H DW (64*80) +6000H DW (65*80) +2000H DW (65*80) +4000H DW (65*80) +6000H DW (66*80) +2000H DW (66*80) +4000H DW (66*80) +6000H DW (67*80) +2000H DW (67*80) +4000H DW (67*80) +6000H DW (68*80) +2000H DW (68*80) +4000H DW (68*80) +6000H DW (69*80) +2000H DW (69*80) +4000H DW (69*80) +6000H DW (70*80) +2000H DW (70*80) +4000H DW (70*80) +6000H DW (71*80) +2000H DW (71*80) +4000H DW (71*80) +6000H DW (72*80) +2000H DW (72*80) +4000H DW (72*80) +6000H DW (73*80) +2000H DW (73*80) +4000H DW (73*80) +6000H DW (74*80) +2000H DW (74*80) +4000H DW (74*80) +6000H DW (75*80) +2000H DW (75*80