REM > MOS120/SRC REM Source for BBC OS 1.20 : REM Source reconstruction by J.G.Harston REM Main commentrary from Geoff Cox's Micronet disassembly REM Additional commentary by J.G.Harston : IF HIMEM>&FFFF:SYS "OS_GetEnv"TOA$:IFLEFT$(A$,5)<>"B6502":OSCLI"B6502"+MID$(A$,INSTR(A$," ")) ON ERROR REPORT:PRINTERL:END : SYS "OS_GetEnv" TO A$:A$=MID$(A$,1+INSTR(A$," ",1+INSTR(A$," ",1+INSTR(A$," ")))) outfile$="outfile":A%=INSTR(A$," "):IF A%:outfile$=LEFT$(A$,A%-1):A$=MID$(A$,A%+1) target$="bbc" :A%=INSTR(A$," "):IF A%:target$ =LEFT$(A$,A%-1):A$=MID$(A$,A%+1) version$="1.20" :A%=INSTR(A$," "):IF A%:version$=LEFT$(A$,A%-1):A$=MID$(A$,A%+1) flags$="" :A%=INSTR(A$," "):IF A%:flags$ =LEFT$(A$,A%-1):A$=MID$(A$,A%+1) IF outfile$="-?":ERROR 220,"Syntax: Basic -quit MOS/src ()":END : PRINT "Assembling: BBC MOS version ";version$ PRINT "Target: ";target$ PRINT "Outfile: ";outfile$ ON ERROR REPORT:PRINT " at line ";ERL:END : DIM mcode% &4100 load%=&C000 title$="" : IF target$="bbc" THEN title$="BBC Computer" ENDIF : IF target$="usa" THEN title$="Acorn OS" ENDIF : IF target$="germany" THEN title$="Acorn OS" ENDIF : IF title$="":ERROR 254,"Unrecognised target":QUIT : : REM MOS entry addresses REM ------------------- OS_CLI=&FFF7:OSBYTE=&FFF4:OSWORD=&FFF1:OSWRCH=&FFEE OSWRCR=&FFEC:OSNEWL=&FFE7:OSASCI=&FFE3:OSRDCH=&FFE0 : REM Vectors REM ------- userv=&200:brkv =&202:irq1v=&204:irq2v=&206 cliv =&208:bytev=&20A:wordv=&20C:wrchv=&20E rdchv=&210:filev=&212:argsv=&214:bgetv=&216 bputv=&218:gbpbv=&21A:findv=&21C:fscv =&21E evntv=&220:uptv =&222:netv =&224:vduv =&226 keyv =&228:insv =&22A:remv =&22C:cnpv =&22E ind1v=&230:ind2v=&232:ind3v=&234 : : FOR opt%=4 TO 7 STEP 3 P%=load%:O%=mcode% [OPT opt% .exec% \ CHARACTER SET \ ============= .LC000 EQUD &00000000:EQUD &00000000 :\ CHR$32 - EQUD &18181818:EQUD &00180018 :\ CHR$33 - ! EQUD &006C6C6C:EQUD &00000000 :\ CHR$34 - "" EQUD &367F3636:EQUD &0036367F :\ CHR$35 - # EQUD &3E683F0C:EQUD &00187E0B :\ CHR$36 - $ EQUD &180C6660:EQUD &00066630 :\ CHR$37 - % EQUD &386C6C38:EQUD &003B666D :\ CHR$38 - & EQUD &0030180C:EQUD &00000000 :\ CHR$39 - ' EQUD &3030180C:EQUD &000C1830 :\ CHR$40 - "(" EQUD &0C0C1830:EQUD &0030180C :\ CHR$41 - ")" EQUD &3C7E1800:EQUD &0000187E :\ CHR$42 - * EQUD &7E181800:EQUD &00001818 :\ CHR$43 - + EQUD &00000000:EQUD &30181800 :\ CHR$44 - , EQUD &7E000000:EQUD &00000000 :\ CHR$45 - - EQUD &00000000:EQUD &00181800 :\ CHR$46 - . EQUD &180C0600:EQUD &00006030 :\ CHR$47 - / EQUD &7E6E663C:EQUD &003C6676 :\ CHR$48 - 0 EQUD &18183818:EQUD &007E1818 :\ CHR$49 - 1 EQUD &0C06663C:EQUD &007E3018 :\ CHR$50 - 2 EQUD &1C06663C:EQUD &003C6606 :\ CHR$51 - 3 EQUD &6C3C1C0C:EQUD &000C0C7E :\ CHR$52 - 4 EQUD &067C607E:EQUD &003C6606 :\ CHR$53 - 5 EQUD &7C60301C:EQUD &003C6666 :\ CHR$54 - 6 EQUD &180C067E:EQUD &00303030 :\ CHR$55 - 7 EQUD &3C66663C:EQUD &003C6666 :\ CHR$56 - 8 EQUD &3E66663C:EQUD &00380C06 :\ CHR$57 - 9 EQUD &18180000:EQUD &00181800 :\ CHR$58 - : EQUD &18180000:EQUD &30181800 :\ CHR$59 - ; EQUD &6030180C:EQUD &000C1830 :\ CHR$60 - < EQUD &007E0000:EQUD &0000007E :\ CHR$61 - = EQUD &060C1830:EQUD &0030180C :\ CHR$62 - > EQUD &180C663C:EQUD &00180018 :\ CHR$63 - ? EQUD &6A6E663C:EQUD &003C606E :\ CHR$64 - @ EQUD &7E66663C:EQUD &00666666 :\ CHR$65 - A EQUD &7C66667C:EQUD &007C6666 :\ CHR$66 - B EQUD &6060663C:EQUD &003C6660 :\ CHR$67 - C EQUD &66666C78:EQUD &00786C66 :\ CHR$68 - D EQUD &7C60607E:EQUD &007E6060 :\ CHR$69 - E EQUD &7C60607E:EQUD &00606060 :\ CHR$70 - F EQUD &6E60663C:EQUD &003C6666 :\ CHR$71 - G EQUD &7E666666:EQUD &00666666 :\ CHR$72 - H EQUD &1818187E:EQUD &007E1818 :\ CHR$73 - I EQUD &0C0C0C3E:EQUD &00386C0C :\ CHR$74 - J EQUD &70786C66:EQUD &00666C78 :\ CHR$75 - K EQUD &60606060:EQUD &007E6060 :\ CHR$76 - L EQUD &6B7F7763:EQUD &0063636B :\ CHR$77 - M EQUD &7E766666:EQUD &0066666E :\ CHR$78 - N EQUD &6666663C:EQUD &003C6666 :\ CHR$79 - O EQUD &7C66667C:EQUD &00606060 :\ CHR$80 - P EQUD &6666663C:EQUD &00366C6A :\ CHR$81 - Q EQUD &7C66667C:EQUD &0066666C :\ CHR$82 - R EQUD &3C60663C:EQUD &003C6606 :\ CHR$83 - S EQUD &1818187E:EQUD &00181818 :\ CHR$84 - T EQUD &66666666:EQUD &003C6666 :\ CHR$85 - U EQUD &66666666:EQUD &00183C66 :\ CHR$86 - V EQUD &6B6B6363:EQUD &0063777F :\ CHR$87 - W EQUD &183C6666:EQUD &0066663C :\ CHR$88 - X EQUD &3C666666:EQUD &00181818 :\ CHR$89 - Y EQUD &180C067E:EQUD &007E6030 :\ CHR$90 - Z EQUD &6060607C:EQUD &007C6060 :\ CHR$91 - [ EQUD &18306000:EQUD &0000060C :\ CHR$92 - \ EQUD &0606063E:EQUD &003E0606 :\ CHR$93 - ] EQUD &42663C18:EQUD &00000000 :\ CHR$94 - ^ EQUD &00000000:EQUD &FF000000 :\ CHR$95 - _ EQUD &7C30361C:EQUD &007E3030 :\ CHR$96 - ` EQUD &063C0000:EQUD &003E663E :\ CHR$97 - a EQUD &667C6060:EQUD &007C6666 :\ CHR$98 - b EQUD &663C0000:EQUD &003C6660 :\ CHR$99 - c EQUD &663E0606:EQUD &003E6666 :\ CHR$100 - d EQUD &663C0000:EQUD &003C607E :\ CHR$101 - e EQUD &7C30301C:EQUD &00303030 :\ CHR$102 - f EQUD &663E0000:EQUD &3C063E66 :\ CHR$103 - g EQUD &667C6060:EQUD &00666666 :\ CHR$104 - h EQUD &18380018:EQUD &003C1818 :\ CHR$105 - i EQUD &18380018:EQUD &70181818 :\ CHR$106 - j EQUD &6C666060:EQUD &00666C78 :\ CHR$107 - k EQUD &18181838:EQUD &003C1818 :\ CHR$108 - l EQUD &7F360000:EQUD &00636B6B :\ CHR$109 - m EQUD &667C0000:EQUD &00666666 :\ CHR$110 - n EQUD &663C0000:EQUD &003C6666 :\ CHR$111 - o EQUD &667C0000:EQUD &60607C66 :\ CHR$112 - p EQUD &663E0000:EQUD &07063E66 :\ CHR$113 - q EQUD &766C0000:EQUD &00606060 :\ CHR$114 - r EQUD &603E0000:EQUD &007C063C :\ CHR$115 - s EQUD &307C3030:EQUD &001C3030 :\ CHR$116 - t EQUD &66660000:EQUD &003E6666 :\ CHR$117 - u EQUD &66660000:EQUD &00183C66 :\ CHR$118 - v EQUD &6B630000:EQUD &00367F6B :\ CHR$119 - w EQUD &3C660000:EQUD &00663C18 :\ CHR$120 - x EQUD &66660000:EQUD &3C063E66 :\ CHR$121 - y EQUD &0C7E0000:EQUD &007E3018 :\ CHR$122 - z EQUD &7018180C:EQUD &000C1818 :\ CHR$123 - { EQUD &00181818:EQUD &00181818 :\ CHR$124 - | EQUD &0E181830:EQUD &00301818 :\ CHR$125 - } EQUD &00466B31:EQUD &00000000 :\ CHR$126 - ~ EQUD &FFFFFFFF:EQUD &FFFFFFFF :\ CHR$127 - \************************************************************************** \************************************************************************** \** ** \** VDU DRIVERS ** \** ** \************************************************************************** \************************************************************************** \ .LC300:JMP LCB1D :\ Initialise VDU drivers with MODE A .LC303:EQUB 13:EQUS "BBC Computer":EQUB 0 .LC312:EQUS "16K":EQUB 7:EQUB 0 .LC317:EQUS "32K":EQUB 7:EQUB 0 .LC31C:EQUB 8:EQUB 13:EQUB 13 :\ Terminated by next byte \****** 16-COLOUR MODE BYTE MASK LOOK-UP TABLE ****** .LC31F EQUW &00 :\ 00000000 EQUW &11 :\ 00010001 EQUW &22 :\ 00100010 EQUW &33 :\ 00110011 EQUW &44 :\ 01000100 EQUW &55 :\ 01010101 EQUW &66 :\ 01100110 EQUW &77 :\ 01110111 EQUW &88 :\ 10001000 EQUW &99 :\ 10011001 EQUW &AA :\ 10101010 EQUW &BB :\ 10111011 EQUW &CC :\ 11001100 EQUW &DD :\ 11011101 EQUW &EE :\ 11101110 EQUW &FF :\ 11111111 \****** 4-COLOUR MODE BYTE MASK LOOK-UP TABLE ****** .LC32F EQUW &00 :\ 00000000 EQUW &55 :\ 01010101 EQUW &AA :\ 10101010 EQUW &FF :\ 11111111 \****** VDU CONTROL CODE DISPATCH TABLE - ADDRESS LOW BYTES ****** .LC333 EQUB LC511 AND 255 :\ VDU 0 EQUB LC53B AND 255 :\ VDU 1 EQUB LC596 AND 255 :\ VDU 2 EQUB LC5A1 AND 255 :\ VDU 3 EQUB LC5AD AND 255 :\ VDU 4 EQUB LC5B9 AND 255 :\ VDU 5 EQUB LC511 AND 255 :\ VDU 6 EQUB LE86F AND 255 :\ VDU 7 EQUB LC5C5 AND 255 :\ VDU 8 EQUB LC664 AND 255 :\ VDU 9 EQUB LC6F0 AND 255 :\ VDU 10 EQUB LC65B AND 255 :\ VDU 11 EQUB LC759 AND 255 :\ VDU 12 EQUB LC7AF AND 255 :\ VDU 13 EQUB LC58D AND 255 :\ VDU 14 EQUB LC5A6 AND 255 :\ VDU 15 EQUB LC7C0 AND 255 :\ VDU 16 EQUB LC7F9 AND 255 :\ VDU 17 EQUB LC7FD AND 255 :\ VDU 18 EQUB LC892 AND 255 :\ VDU 19 EQUB LC839 AND 255 :\ VDU 20 EQUB LC59B AND 255 :\ VDU 21 EQUB LC8EB AND 255 :\ VDU 22 EQUB LC8F1 AND 255 :\ VDU 23 EQUB LCA39 AND 255 :\ VDU 24 EQUB LC98C AND 255 :\ VDU 25 EQUB LC9BD AND 255 :\ VDU 26 EQUB LC511 AND 255 :\ VDU 27 EQUB LC6FA AND 255 :\ VDU 28 EQUB LCAA2 AND 255 :\ VDU 29 EQUB LC779 AND 255 :\ VDU 30 EQUB LC787 AND 255 :\ VDU 31 EQUB LCAAC AND 255 :\ VDU 127 \****** VDU CONTROL CODE DISPATCH TABLE - ADDRESS HIGH BYTES ****** .LC354 \ 1xxxxxxx - no parameters, address high byte \ 0aaapppp - parameter count 16-p, address high byte &C3+a \ EQUB LC511 DIV 256 :\ VDU 0 - no parameters EQUB (LC53B-LC300) DIV 16 + (16-1) :\ VDU 1 - 1 parameter EQUB LC596 DIV 256 :\ VDU 2 - no parameters EQUB LC5A1 DIV 256 :\ VDU 3 - no parameters EQUB LC5AD DIV 256 :\ VDU 4 - no parameters EQUB LC5B9 DIV 256 :\ VDU 5 - no parameters EQUB LC511 DIV 256 :\ VDU 6 - no parameters EQUB LE86F DIV 256 :\ VDU 7 - no parameters EQUB LC5C5 DIV 256 :\ VDU 8 - no parameters EQUB LC664 DIV 256 :\ VDU 9 - no parameters EQUB LC6F0 DIV 256 :\ VDU 10 - no parameters EQUB LC65B DIV 256 :\ VDU 11 - no parameters EQUB LC759 DIV 256 :\ VDU 12 - no parameters EQUB LC7AF DIV 256 :\ VDU 13 - no parameters EQUB LC58D DIV 256 :\ VDU 14 - no parameters EQUB LC5A6 DIV 256 :\ VDU 15 - no parameters EQUB LC7C0 DIV 256 :\ VDU 16 - no parameters EQUB (LC7F9-LC300) DIV 16 + (16-1) :\ VDU 17 - 1 parameter EQUB (LC7FD-LC300) DIV 16 + (16-2) :\ VDU 18 - 2 parameters EQUB (LC892-LC300) DIV 16 + (17-5) :\ VDU 19 - 5 parameters EQUB LC839 DIV 256 :\ VDU 20 - no parameters EQUB LC59B DIV 256 :\ VDU 21 - no parameters EQUB (LC8EB-LC300) DIV 16 + (16-1) :\ VDU 22 - 1 parameter EQUB (LC8F1-LC300) DIV 16 + (16-9) :\ VDU 23 - 9 parameters EQUB (LCA39-LC300) DIV 16 + (16-8) :\ VDU 24 - 8 parameters EQUB (LC9AC-LC300) DIV 16 + (16-5) :\ VDU 25 - 5 parameters EQUB LC9BD DIV 256 :\ VDU 26 - no parameters EQUB LC511 DIV 256 :\ VDU 27 - no parameters EQUB (LC6FA-LC300) DIV 16 + (16-4) :\ VDU 28 - 4 parameters EQUB (LCAA2-LC300) DIV 16 + (16-4) :\ VDU 29 - 4 parameters EQUB LC779 DIV 256 :\ VDU 30 - no parameters EQUB (LC787-LC300) DIV 16 + (16-2) :\ VDU 31 - 2 parameters EQUB LCAAC DIV 256 :\ VDU 127 - no parameters \****** 640 MULTIPLICATION TABLE 40COL, 80COL MODES HIBYTE, LOBYTE ****** .LC375 EQUW &0000 :\ 0*640 = &0000 EQUW &8002 :\ 1*640 = &0280 EQUW &0005 :\ 2*640 = &0500 EQUW &8007 :\ 3*640 = &0780 EQUW &000A :\ 4*640 EQUW &800C :\ 5*640 EQUW &000F :\ 6*640 EQUW &8011 :\ 7*640 EQUW &0014 :\ 8*640 EQUW &8016 :\ 9*640 EQUW &0019 :\ 10*640 EQUW &801B :\ 11*640 EQUW &001E :\ 12*640 EQUW &8020 :\ 13*640 EQUW &0023 :\ 14*640 EQUW &8025 :\ 15*640 EQUW &0028 :\ 16*640 EQUW &802A :\ 17*640 EQUW &002D :\ 18*640 EQUW &802F :\ 19*640 EQUW &0032 :\ 20*640 EQUW &8034 :\ 21*640 EQUW &0037 :\ 22*640 EQUW &8039 :\ 23*640 EQUW &003C :\ 24*640 EQUW &803E :\ 25*640 EQUW &0041 :\ 26*640 EQUW &8043 :\ 27*640 EQUW &0046 :\ 28*640 EQUW &8048 :\ 29*640 EQUW &004B :\ 30*640 EQUW &804D :\ 31*640 = &4D80 \****** 40 MULTIPLICATION TABLE TELETEXT MODE HIBYTE, LOBYTE ****** .LC3B5 EQUW &0000 :\ 0*40 = &0000 EQUW &2800 :\ 1*40 = &0028 EQUW &5000 :\ 2*40 EQUW &7800 :\ 3*40 EQUW &A000 :\ 4*40 EQUW &C800 :\ 5*40 EQUW &F000 :\ 6*40 EQUW &1801 :\ 7*40 EQUW &4001 :\ 8*40 EQUW &6801 :\ 9*40 EQUW &9001 :\ 10*40 EQUW &B801 :\ 11*40 EQUW &E001 :\ 12*40 EQUW &0802 :\ 13*40 EQUW &3002 :\ 14*40 EQUW &5802 :\ 15*40 EQUW &8002 :\ 16*40 EQUW &A802 :\ 17*40 EQUW &D002 :\ 18*40 EQUW &F802 :\ 19*40 EQUW &2003 :\ 20*40 EQUW &4803 :\ 21*40 EQUW &7003 :\ 22*40 EQUW &9803 :\ 23*40 = &0398 EQUW &C003 :\ 24*40 = &03C0 \****** TEXT WINDOW - BOTTOM ROW LOOK-UP TABLE ****** .LC3E7 EQUB 32-1 :\ MODE 0 - 32 ROWS EQUB 32-1 :\ MODE 1 - 32 ROWS EQUB 32-1 :\ MODE 2 - 32 ROWS EQUB 25-1 :\ MODE 3 - 25 ROWS EQUB 32-1 :\ MODE 4 - 32 ROWS EQUB 32-1 :\ MODE 5 - 32 ROWS EQUB 25-1 :\ MODE 6 - 25 ROWS EQUB 25-1 :\ MODE 7 - 25 ROWS \****** TEXT WINDOW - RIGHT HAND COLUMN LOOK-UP TABLE ****** .LC3EF EQUB 80-1 :\ MODE 0 - 80 COLUMNS EQUB 40-1 :\ MODE 1 - 40 COLUMNS EQUB 20-1 :\ MODE 2 - 20 COLUMNS EQUB 80-1 :\ MODE 3 - 80 COLUMNS EQUB 40-1 :\ MODE 4 - 40 COLUMNS EQUB 20-1 :\ MODE 5 - 20 COLUMNS EQUB 40-1 :\ MODE 6 - 40 COLUMNS EQUB 40-1 :\ MODE 7 - 40 COLUMNS \************************************************************************* \* * \* SEVERAL OF THE FOLLOWING TABLES OVERLAP EACH OTHER * \* SOME ARE DUAL PURPOSE * \* * \************************************************************************* \************** VIDEO ULA CONTROL REGISTER SETTINGS *********************** .LC3F7 EQUB &9C :\ MODE 0 - 10011100 EQUB &D8 :\ MODE 1 - 11011000 EQUB &F4 :\ MODE 2 - 11110100 EQUB &9C :\ MODE 3 - 10011100 EQUB &88 :\ MODE 4 - 10001000 EQUB &C4 :\ MODE 5 - 11000100 EQUB &88 :\ MODE 6 - 10001000 EQUB &4B :\ MODE 7 - 01001011 \******** NUMBER OF BYTES PER CHARACTER FOR EACH DISPLAY MODE ************ .LC3FF EQUB 8 :\ MODE 0 EQUB 16 :\ MODE 1 EQUB 32 :\ MODE 2 EQUB 8 :\ MODE 3 EQUB 8 :\ MODE 4 EQUB 16 :\ MODE 5 EQUB 8 :\ MODE 6 EQUB 1 :\ MODE 7 \******************* MASK TABLE FOR 2 COLOUR MODES ********************** .LC407 EQUB &AA :\ 10101010 EQUB &55 :\ 01010101 \****************** MASK TABLE FOR 4 COLOUR MODES *********************** .LC409 EQUB &88 :\ 10001000 EQUB &44 :\ 01000100 EQUB &22 :\ 00100010 EQUB &11 :\ 00010001 \********** MASK TABLE FOR 4 COLOUR MODES FONT FLAG MASK TABLE ********** .LC40D EQUB &80 :\ 10000000 EQUB &40 :\ 01000000 EQUB &20 :\ 00100000 EQUB &10 :\ 00010000 EQUB &08 :\ 00001000 EQUB &04 :\ 00000100 EQUB &02 :\ 00000010 - NEXT BYTE IN FOLLOWING TABLE \********* NUMBER OF TEXT COLOURS -1 FOR EACH MODE ************************ .LC414 EQUB 2-1 :\ MODE 0 - 2 COLOURS EQUB 4-1 :\ MODE 1 - 4 COLOURS EQUB 16-1 :\ MODE 2 - 16 COLOURS EQUB 2-1 :\ MODE 3 - 2 COLOURS EQUB 2-1 :\ MODE 4 - 2 COLOURS EQUB 4-1 :\ MODE 5 - 4 COLOURS EQUB 2-1 :\ MODE 6 - 2 COLOURS EQUB 1-1 :\ MODE 7 - 1 'COLOUR' \************** GCOL PLOT OPTIONS PROCESSING LOOK UP TABLE *************** .LC41C EQUB &FF :\ 11111111 - 0 EQUB &00 :\ 00000000 - 1 EQUB &00 :\ 00000000 - 2 EQUB &FF :\ 11111111 - 3 EQUB &FF :\ 11111111 - 4 EQUB &FF :\ 11111111 - 5 EQUB &FF :\ 11111111 - 6 EQUB &00 :\ 00000000 - 7 \********** 2 COLOUR MODES PARAMETER LOOK UP TABLE WITHIN TABLE ********** .LC424 EQUB &00 :\ 00000000 EQUB &FF :\ 11111111 \*************** 4 COLOUR MODES PARAMETER LOOK UP TABLE ****************** .LC426 EQUB &00 :\ 00000000 EQUB &0F :\ 00001111 EQUB &F0 :\ 11110000 EQUB &FF :\ 11111111 \***************16 COLOUR MODES PARAMETER LOOK UP TABLE ****************** .LC42A EQUB &00 :\ 00000000 EQUB &03 :\ 00000011 EQUB &0C :\ 00001100 EQUB &0F :\ 00001111 EQUB &30 :\ 00110000 EQUB &33 :\ 00110011 EQUB &3C :\ 00111100 EQUB &3F :\ 00111111 EQUB &C0 :\ 11000000 EQUB &C3 :\ 11000011 EQUB &CC :\ 11001100 EQUB &CF :\ 11001111 EQUB &F0 :\ 11110000 EQUB &F3 :\ 11110011 EQUB &FC :\ 11111100 EQUB &FF :\ 11111111 \********** DISPLAY MODE PIXELS/BYTE-1 TABLE ********************* .LC43A EQUB 8-1 :\ MODE 0 - 8 PIXELS/BYTE EQUB 4-1 :\ MODE 1 - 4 PIXELS/BYTE EQUB 2-1 :\ MODE 2 - 2 PIXELS/BYTE EQUB 1-1 :\ MODE 3 - 1 PIXEL/BYTE (NON-GRAPHICS) EQUB 8-1 :\ MODE 4 - 8 PIXELS/BYTE EQUB 4-1 :\ MODE 5 - 4 PIXELS/BYTE \********* SCREEN DISPLAY MEMORY TYPE TABLE OVERLAPS ************ .LC440 EQUB 1-1 :\ MODE 6 - 1 PIXEL/BYTE // MODE 0 - TYPE 0 \***** SOUND PITCH OFFSET BY CHANNEL TABLE WITHIN TABLE ********** .LC441 EQUB &00 :\ MODE 7 - 1 PIXEL/BYTE // MODE 1 - TYPE 0 // CHANNEL 0 EQUB &00 :\ // MODE 2 - TYPE 0 // CHANNEL 1 EQUB &01 :\ // MODE 3 - TYPE 1 // CHANNEL 2 EQUB &02 :\ // MODE 4 - TYPE 2 // CHANNEL 3 \**** REST OF DISPLAY MEMORY TYPE TABLE **** EQUB &02 :\ // MODE 5 - TYPE 2 EQUB &03 :\ // MODE 6 - TYPE 3 \***************** VDU SECTION CONTROL NUMBERS *************************** .LC447 EQUB &04 :\ 00000100 // MODE 7 - TYPE 4 EQUB &00 :\ 00000000 EQUB &06 :\ 00000110 EQUB &02 :\ 00000010 \*********** CRTC SETUP PARAMETERS TABLE 1 WITHIN TABLE ****************** .LC44B EQUB &0D :\ 00001101 EQUB &05 :\ 00000101 EQUB &0D :\ 00001101 EQUB &05 :\ 00000101 \*********** CRTC SETUP PARAMETERS TABLE 2 WITHIN TABLE ***************** .LC44F EQUB &04 :\ 00000100 EQUB &04 :\ 00000100 EQUB &0C :\ 00001100 EQUB &0C :\ 00001100 EQUB &04 :\ 00000100 \**** REST OF VDU SECTION CONTROL NUMBERS **** .LC454 EQUB &02 :\ 00000010 EQUB &32 :\ 00110010 EQUB &7A :\ 01111010 EQUB &92 :\ 10010010 EQUB &E6 :\ 11100110 \************** MSB OF MEMORY OCCUPIED BY SCREEN BUFFER ***************** .LC459 EQUB &50 :\ Type 0, &5000 - 20K EQUB &40 :\ Type 1, &4000 - 16K EQUB &28 :\ Type 2, &2800 - 10K EQUB &20 :\ Type 3, &2000 - 8K EQUB &04 :\ Type 4, &0400 - 1K \************ MSB OF FIRST LOCATION OCCUPIED BY SCREEN BUFFER ************ .LC45E EQUB &30 :\ Type 0, &3000 EQUB &40 :\ Type 1, &4000 EQUB &58 :\ Type 2, &5800 EQUB &60 :\ Type 3, &6000 EQUB &7C :\ Type 4, &7C00 \***************** NUMBER OF BYTES PER ROW ******************************* .LC463 EQUB 40 EQUB 64 EQUB 128 \******** ROW MULTIPLIACTION TABLE POINTER TO LOOK UP TABLE ************** .LC466 EQUB LC3B5 AND 255 EQUB LC375 AND 255 EQUB LC375 AND 255 \********** CRTC CURSOR END REGISTER SETTING LOOK UP TABLE *************** .LC469 EQUB &0B :\ 00001011 EQUB &17 :\ 00010111 EQUB &23 :\ 00100011 EQUB &2F :\ 00101111 EQUB &3B :\ 00111011 \************* 6845 REGISTERS 0-11 FOR SCREEN TYPE 0 - MODES 0-2 ********* .LC46E EQUB &7F :\ 0 Horizontal Total =128 EQUB &50 :\ 1 Horizontal Displayed =80 EQUB &62 :\ 2 Horizontal Sync =&62 EQUB &28 :\ 3 HSync Width+VSync =&28 VSync=2, HSync Width=8 EQUB &26 :\ 4 Vertical Total =38 EQUB &00 :\ 5 Vertial Adjust =0 EQUB &20 :\ 6 Vertical Displayed =32 EQUB &22 :\ 7 VSync Position =&22 EQUB &01 :\ 8 Interlace+Cursor =&01 Cursor=0, Display=0, Interlace=Sync EQUB &07 :\ 9 Scan Lines/Character =8 EQUB &67 :\ 10 Cursor Start Line =&67 Blink=On, Speed=1/32, Line=7 EQUB &08 :\ 11 Cursor End Line =8 \************* 6845 REGISTERS 0-11 FOR SCREEN TYPE 1 - MODE 3 ************ .LC47A EQUB &7F :\ 0 Horizontal Total =128 EQUB &50 :\ 1 Horizontal Displayed =80 EQUB &62 :\ 2 Horizontal Sync =&62 EQUB &28 :\ 3 HSync Width+VSync =&28 VSync=2, HSync=8 EQUB &1E :\ 4 Vertical Total =30 EQUB &02 :\ 5 Vertical Adjust =2 EQUB &19 :\ 6 Vertical Displayed =25 EQUB &1B :\ 7 VSync Position =&1B EQUB &01 :\ 8 Interlace+Cursor =&01 Cursor=0, Display=0, Interlace=Sync EQUB &09 :\ 9 Scan Lines/Character =10 EQUB &67 :\ 10 Cursor Start Line =&67 Blink=On, Speed=1/32, Line=7 EQUB &09 :\ 11 Cursor End Line =9 \************ 6845 REGISTERS 0-11 FOR SCREEN TYPE 2 - MODES 4-5 ********** .LC486 EQUB &3F :\ 0 Horizontal Total =64 EQUB &28 :\ 1 Horizontal Displayed =40 EQUB &31 :\ 2 Horizontal Sync =&31 EQUB &24 :\ 3 HSync Width+VSync =&24 VSync=2, HSync=4 EQUB &26 :\ 4 Vertical Total =38 EQUB &00 :\ 5 Vertical Adjust =0 EQUB &20 :\ 6 Vertical Displayed =32 EQUB &22 :\ 7 VSync Position =&22 EQUB &01 :\ 8 Interlace+Cursor =&01 Cursor=0, Display=0, Interlace=Sync EQUB &07 :\ 9 Scan Lines/Character =8 EQUB &67 :\ 10 Cursor Start Line =&67 Blink=On, Speed=1/32, Line=7 EQUB &08 :\ 11 Cursor End Line =8 \********** 6845 REGISTERS 0-11 FOR SCREEN TYPE 3 - MODE 6 *************** .LC492 EQUB &3F :\ 0 Horizontal Total =64 EQUB &28 :\ 1 Horizontal Displayed =40 EQUB &31 :\ 2 Horizontal Sync =&31 EQUB &24 :\ 3 HSync Width+VSync =&24 VSync=2, HSync=4 EQUB &1E :\ 4 Vertical Total =30 EQUB &02 :\ 5 Vertical Adjust =0 EQUB &19 :\ 6 Vertical Displayed =25 EQUB &1B :\ 7 VSync Position =&1B EQUB &01 :\ 8 Interlace+Cursor =&01 Cursor=0, Display=0, Interlace=Sync EQUB &09 :\ 9 Scan Lines/Character =10 EQUB &67 :\ 10 Cursor Start Line =&67 Blink=On, Speed=1/32, Line=7 EQUB &09 :\ 11 Cursor End Line =9 \********* 6845 REGISTERS 0-11 FOR SCREEN TYPE 4 - MODE 7 **************** .LC49E EQUB &3F :\ 0 Horizontal Total =64 EQUB &28 :\ 1 Horizontal Displayed =40 EQUB &33 :\ 2 Horizontal Sync =&33 Note, &31 is a better value EQUB &24 :\ 3 HSync Width+VSync =&24 VSync=2, HSync=4 EQUB &1E :\ 4 Vertical Total =30 EQUB &02 :\ 5 Vertical Adjust =2 EQUB &19 :\ 6 Vertical Displayed =25 EQUB &1B :\ 7 VSync Position =&1B EQUB &93 :\ 8 Interlace+Cursor =&93 Cursor=2, Display=1, Interlace=Sync+Video EQUB &12 :\ 9 Scan Lines/Character =19 EQUB &72 :\ 10 Cursor Start Line =&72 Blink=On, Speed=1/32, Line=18 EQUB &13 :\ 11 Cursor End Line =19 \************* VDU ROUTINE VECTOR ADDRESSES ****************************** .LC4AA EQUB &86 :\ 10000110 EQUB &D3 :\ 11010011 EQUB &7E :\ 01111110 EQUB &D3 :\ 11010011 \************ VDU ROUTINE BRANCH VECTOR ADDRESS LO *********************** .LC4AE EQUB LD36A AND 255 EQUB LD374 AND 255 EQUB LD342 AND 255 EQUB LD34B AND 255 \************ VDU ROUTINE BRANCH VECTOR ADDRESS HI *********************** .LC4B2 EQUB LD36A DIV 256 EQUB LD374 DIV 256 EQUB LD342 DIV 256 EQUB LD34B DIV 256 \*********** TELETEXT CHARACTER CONVERSION TABLE ************************ .LC4B6 EQUB ASC"#" :\ '#' -> '_' EQUB ASC"_" :\ '_' -> '`' EQUB ASC"`" :\ '`' -> '#' EQUB ASC"#" :\ '#' \*********** SOFT CHARACTER RAM ALLOCATION ***************************** .LC4BA EQUB &04 :\ &20-&3F - OSHWM+&0400 EQUB &05 :\ &40-&5F - OSHWM+&0500 EQUB &06 :\ &60-&7F - OSHWM+&0600 EQUB &00 :\ &80-&9F - &0C00 EQUB &01 :\ &A0-&BF - OSHWM+&0100 EQUB &02 :\ &C0-&DF - OSHWM+&0200 \************************************************************************* \* * \* VDU Variables * \* * \************************************************************************* \ D0 VDU status \ Bit 0 printer output enabled \ 1 scrolling disabled \ 2 paged scrolling enabled \ 3 software scrolling selected \ 4 not used \ 5 printing at graphics cursor enabled \ 6 cursor editing mode enabled \ 7 screen disabled \ \ D1 byte mask for current graphics point \ D2/3 text colour bytes to be ORed and EORed into memory \ D4/5 graphics colour bytes to be ORed and EORed into memory \ D6/7 address of top line of current graphics cell \ D8/9 address of top scan line of current text character \ DA/F temporary workspace \ E0/1 CRTC row multiplication table pointer \ \ 246 Character definition explosion switch \ \ 248 current video ULA control regiter setting \ 249 current pallette setting \ \ 251 flash counter \ 252 mark-space count \ 253 space period count \ \ 256 EXEC file handle \ 257 SPOOL file handle \ \ 260 Econet OSWRCH interception flag \ 267 bit 7 set ignore start up message \ 268 length of key string \ 269 print line counter \ 26A number of items in VDU queque \ 26B TAB key value \ 26C ESCAPE character \ \ 27D cursor editing status \ \ 28F start up options (Keyboard links) \ bits 0-2 default screen Mode \ 3 reverse SHIFT/BREAK \ 4-5 disc timing parameters \ 290 screen display vertical adjustment \ 291 interlace toggle flag \ \ 300/1 graphics window left \ 302/3 graphics window bottom \ 304/5 graphics window right \ 306/7 graphics window top \ 308 text window left \ 309 text window bottom \ 30A text window right \ 30B text window top \ 30C/D graphics origin, horizontal (external values) \ 30E/F graphics origin, vertical (external values) \ \ 310/1 current graphics cursor, horizontal (external values) \ 312/3 current graphics cursor, vertical (external values) \ 314/5 last graphics cursor, horizontal (external values) \ 316/7 last graphics cursor, vertical (external values) \ 318 text column \ 319 text line \ 31A graphics scan line expressed as line of character \ 31B-323 VDU parameters, last parameter in &323 \ 324/5 current graphics cursor, horizontal (internal values) \ 316/7 current graphics cursor, vertical (internal values) \ 328-349 general workspace \ 34A/B text cursor address to CRT controller \ 34C/D width of text window in bytes \ 34E hi byte of address of screen RAM start \ 34F bytes per character \ 350/1 address of window area start \ 352/3 bytes per character row \ 354 high byte of screen RAM size \ 355 Mode \ 356 memory map type \ 357/35A current colours \ 35B/C graphics plot mode \ 35D/E jump vector \ 35F last setting of CRTC Cursor start register \ 360 number of logical colours less 1 \ 361 pixels per byte (0 in text only modes) \ 362/3 colour masks \ 364/5 X/Y for text input cursor \ 366 output cursor character for MODE 7 \ 367 Font flag \ 368/E font location bytes \ 36F-37E Colour palette \************************************************************************** \************************************************************************** \** ** \** VDU DRIVER MAIN ROUTINE called from OSWRCH at E0C4 ** \** ** \** Output a character to the VDU ** \** ** \************************************************************************** \************************************************************************** \ This routine takes up over 40% of the operating system ROM. \ Entry points are variable, as are the results achieved. \ Tracing any particular path is relatively easy but generalising for \ commenting is not. For clarity comments will not be as detailed as \ for later parts of the Operating System. .LC4C0 LDX &026A :\ get number of items in VDU queue BNE LC512 :\ if parameters needed then C512 BIT &D0 :\ else check status byte BVC LC4D8 :\ if cursor editing enabled two cursors exist JSR LC568 :\ swap values JSR LCD6A :\ then set up write cursor BMI LC4D8 :\ if display disabled C4D8 CMP #&0D :\ else if character in A=RETURN teminate edit .LC4D3 BNE LC4D8 :\ else C4D8 JSR LD918 :\ terminate edit .LC4D8 CMP #&7F :\ is character DELETE ? BEQ LC4ED :\ if so C4ED CMP #&20 :\ is it less than space? (i.e. VDU control code) BCC LC4EF :\ if so C4EF BIT &D0 :\ else check VDU byte ahain BMI LC4EA :\ if screen disabled C4EA JSR LCFB7 :\ else display a character JSR LC664 :\ and cursor right .LC4EA JMP LC55E :\ \********* read link addresses and number of parameters ***************** .LC4ED LDA #&20 :\ to replace delete character \********* read link addresses and number of parameters ***************** .LC4EF TAY :\ Y=A LDA LC333,Y :\ get lo byte of link address STA &035D :\ store it in jump vector LDA LC354,Y :\ get hi byte BMI LC545 :\ if negative (as it will be if a direct address) :\ there are no parameters needed :\ so C545 TAX :\ else X=A ORA #&F0 :\ set up negated parameter count STA &026A :\ store it as number of items in VDU queue TXA :\ get back A LSR A :\ A=A/16 LSR A :\ LSR A :\ LSR A :\ CLC :\ clear carry ADC #&C3 :\ add &C3 to get hi byte of link address STA &035E :\ BIT &D0 :\ check if cursor editing enabled BVS LC52F :\ if so re-exchange pointers CLC :\ clear carry .LC511 RTS :\ and exit .LC512 \return with carry clear indicates that printer action not required. \ \********** parameters are outstanding *********************************** \X=&26A = 2 complement of number of parameters X=&FF for 1, FE for 2 etc. STA &0224,X :\ store parameter in queue INX :\ increment X STX &026A :\ store it as VDU queue BNE LC532 :\ if not 0 C532 as more parameters are needed BIT &D0 :\ get VDU status byte BMI LC534 :\ if screen disabled C534 BVS LC526 :\ else if cursor editing C526 JSR LCCF5 :\ execute required function CLC :\ clear carry RTS :\ and exit .LC526 JSR LC568 :\ swap values of cursors JSR LCD6A :\ set up write cursor JSR LCCF5 :\ execute required function .LC52F JSR LC565 :\ re-exchange pointers .LC532 CLC :\ carry clear RTS :\ exit \************************************************************************* \* * \* VDU 1 - SEND NEXT CHARACTER TO PRINTER * \* * \* 1 parameter required * \* * \************************************************************************* \ .LC534 LDY &035E :\ if upper byte of link address not &C5 CPY #&C5 :\ printer is not interested BNE LC532 :\ so C532 .LC53B TAX :\ else X=A LDA &D0 :\ A=VDU status byte LSR A :\ get bit 0 into carry BCC LC511 :\ if printer not enabled exit TXA :\ restore A JMP LE11E :\ else send byte in A (next byte) to printer \*********** if explicit link address found, no parameters *************** .LC545 STA &035E :\ upper byte of link address TYA :\ restore A CMP #&08 :\ is it 7 or less? BCC LC553 :\ if so C553 EOR #&FF :\ invert it CMP #&F2 :\ c is set if A >&0D EOR #&FF :\ re invert .LC553 BIT &D0 :\ VDU status byte BMI LC580 :\ if display disabled C580 PHP :\ push processor flags JSR LCCF5 :\ execute required function PLP :\ get back flags BCC LC561 :\ if carry clear (from C54B/F) \**************** main exit routine ************************************** .LC55E LDA &D0 :\ VDU status byte LSR A :\ Carry is set if printer is enabled .LC561 BIT &D0 :\ VDU status byte BVC LC511 :\ if no cursor editing C511 to exit \***************** cursor editing routines ******************************* .LC565 JSR LCD7A :\ restore normal write cursor .LC568 PHP :\ save flags and PHA :\ A LDX #&18 :\ X=&18 LDY #&64 :\ Y=&64 JSR LCDDE :\ exchange &300/1+X with &300/1+Y JSR LCF06 :\ set up display address JSR LCA02 :\ set cursor position LDA &D0 :\ VDU status byte EOR #&02 :\ invert bit 1 to allow or bar scrolling STA &D0 :\ VDU status byte PLA :\ restore flags and A PLP :\ RTS :\ and exit .LC580 \ EOR #&06 :\ if A<>6 BNE LC58C :\ return via C58C LDA #&7F :\ A=&7F BCC LC5A8 :\ and goto C5A8 ALWAYS!! \******************* check text cursor in use *************************** .LC588 LDA &D0 :\ VDU status byte AND #&20 :\ set A from bit 5 of status byte .LC58C RTS :\ and exit \A=0 if text cursor, &20 if graphics \************************************************************************* \* * \* VDU 14 - SET PAGED MODE * \* * \************************************************************************* \ .LC58D LDY #&00 :\ Y=0 STY &0269 :\ paged mode counter LDA #&04 :\ A=04 BNE LC59D :\ jump to C59D \************************************************************************* \* * \* VDU 2 - PRINTER ON (START PRINT JOB) * \* * \************************************************************************* .LC596 JSR LE1A2 :\ select printer buffer and output character LDA #&94 :\ A=&94 \ ;when inverted at C59B this becomes =&01 \************************************************************************* \* * \* VDU 21 - DISABLE DISPLAY * \* * \************************************************************************* .LC59B EOR #&95 :\ if A=&15 A now =&80, if A=&94 A now =1 .LC59D ORA &D0 :\ VDU status byte set bit 0 or bit 7 BNE LC5AA :\ branch forward to store \************************************************************************* \* * \* VDU 3 - PRINTER OFF (END PRINT JOB) * \* * \************************************************************************* .LC5A1 JSR LE1A2 :\ select printer buffer and output character LDA #&0A :\ A=10 to clear status bits below... \************************************************************************* \* * \* VDU 15 - PAGED MODE OFF * \* * \************************************************************************* \ A=&F or &A .LC5A6 EOR #&F4 :\ convert to &FB or &FE .LC5A8 AND &D0 :\ VDU status byte clear bit 0 or bit 2 of status .LC5AA STA &D0 :\ VDU status byte .LC5AC RTS :\ exit \************************************************************************* \* * \* VDU 4 - OUTPUT AT TEXT CURSOR * \* * \************************************************************************* .LC5AD LDA &0361 :\ pixels per byte BEQ LC5AC :\ if no graphics in current mode C5AC JSR LC951 :\ set CRT controller for text cursor LDA #&DF :\ this to clear bit 5 of status byte BNE LC5A8 :\ via C5A8 exit \************************************************************************* \* * \* VDU 5 - OUTPUT AT GRAPHICS CURSOR * \* * \************************************************************************* .LC5B9 LDA &0361 :\ pixels per byte BEQ LC5AC :\ if none this is text mode so exit LDA #&20 :\ set up graphics cursor JSR LC954 :\ via C954 BNE LC59D :\ set bit 5 via exit C59D \************************************************************************* \* * \* VDU 8 - CURSOR LEFT * \* * \************************************************************************* .LC5C5 JSR LC588 :\ A=0 if text cursor A=&20 if graphics cursor BNE LC61F :\ move cursor left 8 pixels if graphics DEC &0318 :\ else decrement text column LDX &0318 :\ store new text column CPX &0308 :\ if it is less than text window left BMI LC5EE :\ do wraparound cursor to rt of screen 1 line up LDA &034A :\ text cursor 6845 address SEC :\ subtract SBC &034F :\ bytes per character TAX :\ put in X LDA &034B :\ get text cursor 6845 address SBC #&00 :\ subtract 0 CMP &034E :\ compare with hi byte of screen RAM address BCS LC5EA :\ if = or greater ADC &0354 :\ add screen RAM size hi byte to wrap around .LC5EA TAY :\ Y=A JMP LC9F6 :\ Y hi and X lo byte of cursor position \***************** execute wraparound left-up***************************** .LC5EE LDA &030A :\ text window right STA &0318 :\ text column \*************** cursor up *********************************************** .LC5F4 DEC &0269 :\ paged mode counter BPL LC5FC :\ if still greater than 0 skip next instruction INC &0269 :\ paged mode counter to restore X=0 .LC5FC LDX &0319 :\ current text line CPX &030B :\ top of text window BEQ LC60A :\ if its at top of window C60A DEC &0319 :\ else decrement current text line JMP LC6AF :\ and carry on moving cursor \******** cursor at top of window **************************************** .LC60A CLC :\ clear carry JSR LCD3F :\ check for window violatations LDA #&08 :\ A=8 to check for software scrolling BIT &D0 :\ compare against VDU status byte BNE LC619 :\ if not enabled C619 JSR LC994 :\ set screen start register and adjust RAM BNE LC61C :\ jump C61C .LC619 JSR LCDA4 :\ soft scroll 1 line .LC61C JMP LC6AC :\ and exit \**********cursor left and down with graphics cursor in use ************** .LC61F LDX #&00 :\ X=0 to select horizontal parameters \********** cursor down with graphics in use ***************************** \X=2 for vertical or 0 for horizontal .LC621 STX &DB :\ store X JSR LD10D :\ check for window violations LDX &DB :\ restore X SEC :\ set carry LDA &0324,X :\ current graphics cursor X>1=vertical SBC #&08 :\ subtract 8 to move back 1 character STA &0324,X :\ store in current graphics cursor X>1=verticaal BCS LC636 :\ if carry set skip next DEC &0325,X :\ current graphics cursor hi -1 .LC636 LDA &DA :\ &DA=0 if no violation else 1 if vert violation :\2 if horizontal violation BNE LC658 :\ if violation C658 JSR LD10D :\ check for window violations BEQ LC658 :\ if none C658 LDX &DB :\ else get back X LDA &0304,X :\ graphics window rt X=0 top X=2 CPX #&01 :\ is X=0 BCS LC64A :\ if not C64A SBC #&06 :\ else subtract 7 .LC64A STA &0324,X :\ current graphics cursor X>1=vertical LDA &0305,X :\ graphics window hi rt X=0 top X=2 SBC #&00 :\ subtract carry STA &0325,X :\ current graphics cursor X<2=horizontal else vertical TXA :\ A=X BEQ LC660 :\ cursor up .LC658 JMP LD1B8 :\ set up external coordinates for graphics \************************************************************************* \* * \* VDU 11 - CURSOR UP * \* * \************************************************************************* .LC65B JSR LC588 :\ A=0 if text cursor A=&20 if graphics cursor BEQ LC5F4 :\ if text cursor then C5F4 .LC660 LDX #&02 :\ else X=2 BNE LC6B6 :\ goto C6B6 \************************************************************************* \* * \* VDU 9 - CURSOR RIGHT * \* * \************************************************************************* .LC664 LDA &D0 :\ VDU status byte AND #&20 :\ check bit 5 BNE LC6B4 :\ if set then graphics cursor in use so C6B4 LDX &0318 :\ text column CPX &030A :\ text window right BCS LC684 :\ if X exceeds window right then C684 INC &0318 :\ text column LDA &034A :\ text cursor 6845 address ADC &034F :\ add bytes per character TAX :\ X=A LDA &034B :\ text cursor 6845 address ADC #&00 :\ add carry if set JMP LC9F6 :\ use X and Y to set new cursor address \******** text cursor down and right ************************************* .LC684 LDA &0308 :\ text window left STA &0318 :\ text column \******** text cursor down ************************************* .LC68A CLC :\ clear carry JSR LCAE3 :\ check bottom margin, X=line count LDX &0319 :\ current text line CPX &0309 :\ bottom margin BCS LC69B :\ if X=>current bottom margin C69B INC &0319 :\ else increment current text line BCC LC6AF :\ .LC69B JSR LCD3F :\ check for window violations LDA #&08 :\ check bit 3 BIT &D0 :\ VDU status byte BNE LC6A9 :\ if software scrolling enabled C6A9 JSR LC9A4 :\ perform hardware scroll BNE LC6AC :\ .LC6A9 JSR LCDFF :\ execute upward scroll .LC6AC JSR LCEAC :\ clear a line .LC6AF JSR LCF06 :\ set up display address BCC LC732 :\ \*********** graphic cursor right **************************************** .LC6B4 LDX #&00 :\ \************** graphic cursor up (X=2) ********************************** .LC6B6 STX &DB :\ store X JSR LD10D :\ check for window violations LDX &DB :\ get back X CLC :\ clear carry LDA &0324,X :\ current graphics cursor X>1=vertical ADC #&08 :\ Add 8 pixels STA &0324,X :\ current graphics cursor X>1=vertical BCC LC6CB :\ INC &0325,X :\ current graphics cursor X<2=horizontal else vertical .LC6CB LDA &DA :\ A=0 no window violations 1 or 2 indicates violation BNE LC658 :\ if outside window C658 JSR LD10D :\ check for window violations BEQ LC658 :\ if no violations C658 LDX &DB :\ get back X LDA &0300,X :\ graphics window X<2 =left else bottom CPX #&01 :\ If X=0 BCC LC6DF :\ C6DF ADC #&06 :\ else add 7 .LC6DF STA &0324,X :\ current graphics cursor X>1=vertical LDA &0301,X :\ graphics window hi X<2 =left else bottom ADC #&00 :\ add anny carry STA &0325,X :\ current graphics cursor X<2=horizontal else vertical TXA :\ A=X BEQ LC6F5 :\ if X=0 C6F5 cursor down JMP LD1B8 :\ set up external coordinates for graphics \************************************************************************* \* * \* VDU 10 - CURSOR DOWN * \* * \************************************************************************* .LC6F0 JSR LC588 :\ A=0 if text cursor A=&20 if graphics cursor BEQ LC68A :\ if text cursor back to C68A .LC6F5 LDX #&02 :\ else X=2 to indicate vertical movement JMP LC621 :\ move graphics cursor down \************************************************************************* \* * \* VDU 28 - DEFINE TEXT WINDOW * \* * \* 4 parameters * \* * \************************************************************************* \parameters are set up thus \0320 P1 left margin \0321 P2 bottom margin \0322 P3 right margin \0323 P4 top margin \Note that last parameter is always in 0323 .LC6FA LDX &0355 :\ screen mode LDA &0321 :\ get bottom margin CMP &0323 :\ compare with top margin BCC LC758 :\ if bottom margin exceeds top return CMP LC3E7,X :\ text window bottom margin maximum BEQ LC70C :\ if equal then its OK BCS LC758 :\ else exit .LC70C LDA &0322 :\ get right margin TAY :\ put it in Y CMP LC3EF,X :\ text window right hand margin maximum BEQ LC717 :\ if equal then OK BCS LC758 :\ if greater than maximum exit .LC717 SEC :\ set carry to subtract SBC &0320 :\ left margin BMI LC758 :\ if left greater than right exit TAY :\ else A=Y (window width) JSR LCA88 :\ calculate number of bytes in a line LDA #&08 :\ A=8 to set bit of &D0 JSR LC59D :\ indicating that text window is defined LDX #&20 :\ point to parameters LDY #&08 :\ point to text window margins JSR LD48A :\ (&300/3+Y)=(&300/3+X) JSR LCEE8 :\ set up screen address BCS LC779 :\ home cursor within window .LC732 JMP LCA02 :\ set cursor position \************************************************************************* \* * \* OSWORD 9 - READ A PIXEL * \* =POINT(X,Y) * \* * \************************************************************************* \on entry &EF=A=9 \ &F0=X=low byte of parameter block address \ &F1=Y=high byte of parameter block address \ PARAMETER BLOCK \ 0,1=X coordinate \ 2,3=Y coordinate \on exit, result in BLOCK+4 \ =&FF if point was of screen or logical colour of point if on screen \ .LC735 LDY #&03 :\ Y=3 to point to hi byte of Y coordinate .LC737 LDA (&F0),Y :\ get it STA &0328,Y :\ store it DEY :\ point to next byte BPL LC737 :\ transfer till Y=&FF lo byte of X coordinate in &328 LDA #&28 :\ JSR LD839 :\ check window boundaries LDY #&04 :\ Y=4 BNE LC750 :\ jump to C750 \************************************************************************* \* * \* OSWORD 11 - READ PALLETTE * \* * \************************************************************************* \on entry &EF=A=11 \ &F0=X=low byte of parameter block address \ &F1=Y=high byte of parameter block address \ PARAMETER BLOCK \ 0=logical colour to read \on exit, result in BLOCK \ 0=logical colour \ 1=physical colour \ 2=red colour component \ \ 3=green colour component } when set using analogue colours \ 4=blue colour component / .LC748 AND &0360 :\ number of logical colours less 1 TAX :\ put it in X LDA &036F,X :\ colour pallette .LC74F INY :\ increment Y to point to byte 1 .LC750 STA (&F0),Y :\ store data LDA #&00 :\ issue 0s CPY #&04 :\ to next bytes until Y=4 BNE LC74F :\ .LC758 RTS :\ and exit \************************************************************************* \* * \* VDU 12 - CLEAR TEXT SCREEN * \* CLS * \* * \************************************************************************* .LC759 JSR LC588 :\ A=0 if text cursor A=&20 if graphics cursor BNE LC7BD :\ if graphics cursor &C7BD LDA &D0 :\ VDU status byte AND #&08 :\ check if software scrolling (text window set) BNE LC767 :\ if so C767 JMP LCBC1 :\ initialise screen display and home cursor .LC767 LDX &030B :\ top of text window .LC76A STX &0319 :\ current text line JSR LCEAC :\ clear a line LDX &0319 :\ current text line CPX &0309 :\ bottom margin INX :\ X=X+1 BCC LC76A :\ if X at compare is less than bottom margin clear next \************************************************************************* \* * \* VDU 30 - HOME CURSOR * \* * \************************************************************************* .LC779 JSR LC588 :\ A=0 if text cursor A=&20 if graphics cursor .LC77C BEQ LC781 :\ if text cursor C781 JMP LCFA6 :\ home graphic cursor if graphic .LC781 STA &0323 :\ store 0 in last two parameters STA &0322 :\ \************************************************************************* \* * \* VDU 31 - POSITION TEXT CURSOR * \* TAB(X,Y) * \* * \* 2 parameters * \* * \************************************************************************* \0322 = supplied X coordinate \0323 = supplied Y coordinate .LC787 JSR LC588 :\ A=0 if text cursor A=&20 if graphics cursor BNE LC758 :\ exit JSR LC7A8 :\ exchange text column/line with workspace 0328/9 CLC :\ clear carry LDA &0322 :\ get X coordinate ADC &0308 :\ add to text window left STA &0318 :\ store as text column LDA &0323 :\ get Y coordinate CLC :\ ADC &030B :\ add top of text window STA &0319 :\ current text line JSR LCEE8 :\ set up screen address BCC LC732 :\ set cursor position if C=0 (point on screen) .LC7A8 LDX #&18 :\ else point to workspace LDY #&28 :\ and line/column to restore old values JMP LCDDE :\ exchange &300/1+X with &300/1+Y \************************************************************************* \* * \* VDU 13 - CARRIAGE RETURN * \* * \************************************************************************* .LC7AF JSR LC588 :\ A=0 if text cursor A=&20 if graphics cursor BEQ LC7B7 :\ if text C7B7 JMP LCFAD :\ else set graphics cursor to left hand columm .LC7B7 JSR LCE6E :\ set text column to left hand column JMP LC6AF :\ set up cursor and display address .LC7BD JSR LCFA6 :\ home graphic cursor \************************************************************************* \* * \* VDU 16 - CLEAR GRAPHICS SCREEN * \* CLG * \* * \************************************************************************* .LC7C0 LDA &0361 :\ pixels per byte BEQ LC7F8 :\ if 0 current mode has no graphics so exit LDX &035A :\ Background graphics colour LDY &035C :\ background graphics plot mode (GCOL n) JSR LD0B3 :\ set graphics byte mask in &D4/5 LDX #&00 :\ graphics window LDY #&28 :\ workspace JSR LD47C :\ set(300/7+Y) from (300/7+X) SEC :\ set carry LDA &0306 :\ graphics window top lo. SBC &0302 :\ graphics window bottom lo TAY :\ Y=difference INY :\ increment STY &0330 :\ and store in workspace (this is line count) .LC7E1 LDX #&2C :\ LDY #&28 :\ JSR LD6A6 :\ clear line LDA &032E :\ decrement window height in pixels BNE LC7F0 :\ DEC &032F :\ .LC7F0 DEC &032E :\ DEC &0330 :\ decrement line count BNE LC7E1 :\ if <>0 then do it again .LC7F8 RTS :\ exit \************************************************************************* \* * \* VDU 17 - DEFINE TEXT COLOUR * \* COLOUR n * \* * \* 1 parameter * \* * \************************************************************************* \parameter in &0323 .LC7F9 LDY #&00 :\ Y=0 BEQ LC7FF :\ jump to C7FF \************************************************************************* \* * \* VDU 18 - DEFINE GRAPHICS COLOUR * \* GCOL k,c * \* * \* 2 parameters * \* * \************************************************************************* \parameters in 323,322 .LC7FD LDY #&02 :\ Y=2 .LC7FF LDA &0323 :\ get last parameter BPL LC805 :\ if +ve it's foreground colour so C805 INY :\ else Y=Y+1 .LC805 AND &0360 :\ number of logical colours less 1 STA &DA :\ store it LDA &0360 :\ number of logical colours less 1 BEQ LC82B :\ if none exit AND #&07 :\ else limit to an available colour and clear M CLC :\ clear carry ADC &DA :\ Add last parameter to get pointer to table TAX :\ pointer into X LDA LC423,X :\ get plot options from table STA &0357,Y :\ colour Y=0=text fgnd 1= text bkgnd 2=graphics fg etc CPY #&02 :\ If Y>1 BCS LC82C :\ then its graphics so C82C else LDA &0357 :\ foreground text colour EOR #&FF :\ invert STA &D3 :\ text colour byte to be orred or EORed into memory EOR &0358 :\ background text colour STA &D2 :\ text colour byte to be orred or EORed into memory .LC82B RTS :\ and exit .LC82C LDA &0322 :\ get first parameter STA &0359,Y :\ text colour Y=0=foreground 1=background etc. RTS :\ exit .LC833 LDA #&20 :\ STA &0358 :\ background text colour RTS :\ \************************************************************************* \* * \* VDU 20 - RESTORE DEFAULT COLOURS * \* * \************************************************************************* .LC839 LDX #&05 :\ X=5 LDA #&00 :\ A=0 .LC83D STA &0357,X :\ zero all colours DEX :\ BPL LC83D :\ until X=&FF LDX &0360 :\ number of logical colours less 1 BEQ LC833 :\ if none its MODE 7 so C833 LDA #&FF :\ A=&FF CPX #&0F :\ if not mode 2 (16 colours) BNE LC850 :\ goto C850 LDA #&3F :\ else A=&3F .LC850 STA &0357 :\ foreground text colour STA &0359 :\ foreground graphics colour EOR #&FF :\ invert A STA &D2 :\ text colour byte to be orred or EORed into memory STA &D3 :\ text colour byte to be orred or EORed into memory STX &031F :\ set first parameter of 5 CPX #&03 :\ if there are 4 colours BEQ LC874 :\ goto C874 BCC LC885 :\ if less there are 2 colours goto C885 :\else there are 16 colours STX &0320 :\ set second parameter .LC868 JSR LC892 :\ do VDU 19 etc DEC &0320 :\ decrement first parameter DEC &031F :\ and last parameter BPL LC868 :\ RTS :\ \ \********* 4 colour mode ************************************************* .LC874 LDX #&07 :\ X=7 STX &0320 :\ set first parameter .LC879 JSR LC892 :\ and do VDU 19 LSR &0320 :\ DEC &031F :\ BPL LC879 :\ RTS :\ exit \********* 2 colour mode ************************************************ .LC885 LDX #&07 :\ X=7 JSR LC88F :\ execute VDU 19 LDX #&00 :\ X=0 STX &031F :\ store it as .LC88F STX &0320 :\ both parameters \************************************************************************* \* * \* VDU 19 - DEFINE COLOURS * \* [COLOUR l,p] * \* [COLOUR l,r,g,b] * \* * \* 5 parameters * \* * \************************************************************************* \&31F=first parameter logical colour \&320=second physical colour .LC892 PHP :\ push processor flags SEI :\ disable interrupts LDA &031F :\ get first parameter and AND &0360 :\ number of logical colours less 1 TAX :\ toi make legal X=A LDA &0320 :\ A=second parameter .LC89E AND #&0F :\ make legal STA &036F,X :\ colour pallette TAY :\ Y=A LDA &0360 :\ number of logical colours less 1 STA &FA :\ store it CMP #&03 :\ is it 4 colour mode?? PHP :\ save flags TXA :\ A=X .LC8AD ROR A :\ rotate A into &FA ROR &FA :\ BCS LC8AD :\ ASL &FA :\ TYA :\ A=Y ORA &FA :\ TAX :\ LDY #&00 :\ Y=0 .LC8BA PLP :\ check flags PHP :\ BNE LC8CC :\ if A<>3 earlier C8CC AND #&60 :\ else A=&60 to test bits 5 and 6 BEQ LC8CB :\ if not set C8CB CMP #&60 :\ else if both set BEQ LC8CB :\ C8CB TXA :\ A=X EOR #&60 :\ invert BNE LC8CC :\ and if not 0 C8CC .LC8CB TXA :\ X=A .LC8CC JSR LEA11 :\ call Osbyte 155 pass data to pallette register TYA :\ SEC :\ ADC &0360 :\ number of logical colours less 1 TAY :\ TXA :\ ADC #&10 :\ TAX :\ CPY #&10 :\ if Y<16 do it again BCC LC8BA :\ PLP :\ pull flags twice .LC8DE PLP :\ RTS :\ and exit \************************************************************************* \* * \* OSWORD 12 - WRITE PALLETTE * \* * \************************************************************************* \on entry X=&F0, Y=&F1, YX=>parameter block \byte 0 = logical colour; byte 1 physical colour; bytes 2-4=0 .LC8E0 PHP :\ push flags AND &0360 :\ and with number of logical colours less 1 TAX :\ X=A INY :\ Y=Y+1 LDA (&F0),Y :\ get phsical colour JMP LC89E :\ do VDU19 with parameters in X and A \************************************************************************* \* * \* VDU 22 - SELECT MODE * \* MODE n * \* * \* 1 parameter * \* * \************************************************************************* \parameter in &323 .LC8EB LDA &0323 :\ get parameter JMP LCB33 :\ goto CB33 \************************************************************************* \* * \* VDU 23 - DEFINE CHARACTERS * \* * \* 9 parameters * \* * \************************************************************************* \parameters are \31B character to define \31C to 323 definition .LC8F1 LDA &031B :\ get character to define CMP #&20 :\ is it ' ' BCC LC93F :\ if less then it is a control instruction, goto C93F PHA :\ else save parameter LSR A :\ A=A/32 LSR A :\ LSR A :\ LSR A :\ LSR A :\ TAX :\ X=A LDA LC40D,X :\ get font flag mask from table (A=&80/2^X) BIT &0367 :\ font flag BNE LC927 :\ and if A<>0 C927 storage area is established already ORA &0367 :\ or with font flag to set bit found to be 0 STA &0367 :\ font flag TXA :\ get back A AND #&03 :\ And 3 to clear all but bits 0 and 1 CLC :\ clear carry ADC #&BF :\ add &BF (A=&C0,&C1,&C2) to select a character page STA &DF :\ store it LDA &0367,X :\ get font location byte (normally &0C) STA &DD :\ store it LDY #&00 :\ Y=0 so (&DE) holds (&C000 -&C2FF) STY &DC :\ STY &DE :\ .LC920 LDA (&DE),Y :\ transfer page to storage area STA (&DC),Y :\ DEY :\ BNE LC920 :\ .LC927 PLA :\ get back A JSR LD03E :\ set up character definition pointers LDY #&07 :\ Y=7 .LC92D LDA &031C,Y :\ transfer definition parameters STA (&DE),Y :\ to RAM definition DEY :\ BPL LC92D :\ RTS :\ and exit \ PLA :\ Pull A .LC937 RTS :\ and exit \************ VDU EXTENSION ********************************************** .LC938 LDA &031F :\ A=fifth VDU parameter CLC :\ clear carry .LC93C JMP (&0226) :\ jump via VDUV vector \********** VDU control commands ***************************************** .LC93F CMP #&01 :\ is A=1 BCC LC958 :\ if less (0) then set CRT register directly BNE LC93C :\ if not 1 jump to VDUV for VDU extension \********** turn cursor on/off ******************************************* JSR LC588 :\ A=0 if text cursor, A=&20 if graphics cursor BNE LC937 :\ if graphics exit LDA #&20 :\ A=&20 - preload to turn cursor off LDY &031C :\ Y=second VDU parameter BEQ LC954 :\ if 0, jump to C954 to turn cursor off .LC951 LDA &035F :\ get last setting of CRT controller register .LC954 :\ for cursor on LDY #&0A :\ Y=10 - cursor control register number BNE LC985 :\ jump to C985, Y=register, Y=value \********** set CRT controller ******************************************* .LC958 LDA &031D :\ get third LDY &031C :\ and second parameter .LC95E CPY #&07 :\ is Y=7 BCC LC985 :\ if less C985 BNE LC967 :\ else if >7 C967 ADC &0290 :\ else ADD screen vertical display adjustment .LC967 CPY #&08 :\ If Y<>8 BNE LC972 :\ C972 ORA #&00 :\ if bit 7 set BMI LC972 :\ C972 EOR &0291 :\ else EOR with interlace toggle .LC972 CPY #&0A :\ Y=10?? BNE LC985 :\ if not C985 STA &035F :\ last setting of CRT controller register TAY :\ Y=A LDA &D0 :\ VDU status byte AND #&20 :\ check bit 5 printing at graphics cursor?? PHP :\ push flags TYA :\ Y=A LDY #&0A :\ Y=10 PLP :\ pull flags BNE LC98B :\ if graphics in use then C98B .LC985 STY LFE00 :\ else set CRTC address register STA LFE01 :\ and poke new value to register Y .LC98B RTS :\ exit \************************************************************************* \* * \* VDU 25 - PLOT * \* PLOT k,x,y * \* DRAW x,y * \* MOVE x,y * \* PLOT x,y * \* 5 parameters * \* * \************************************************************************* \ .LC98C LDX &0361 :\ pixels per byte BEQ LC938 :\ if no graphics available go to VDU Extension JMP LD060 :\ else enter Plot routine at D060 \********** adjust screen RAM addresses ********************************** .LC994 LDX &0350 :\ window area start address lo LDA &0351 :\ window area start address hi JSR LCCF8 :\ subtract bytes per character row from this BCS LC9B3 :\ if no wraparound needed C9B3 ADC &0354 :\ screen RAM size hi byte to wrap around BCC LC9B3 :\ .LC9A4 LDX &0350 :\ window area start address lo LDA &0351 :\ window area start address hi JSR LCAD4 :\ add bytes per char. row BPL LC9B3 :\ SEC :\ wrap around i other direction SBC &0354 :\ screen RAM size hi byte .LC9B3 STA &0351 :\ window area start address hi STX &0350 :\ window area start address lo LDY #&0C :\ Y=12 BNE LCA0E :\ jump to CA0E \************************************************************************* \* * \* VDU 26 - SET DEFAULT WINDOWS * \* * \************************************************************************* .LC9BD LDA #&00 :\ A=0 LDX #&2C :\ X=&2C .LC9C1 STA &0300,X :\ clear all windows DEX :\ BPL LC9C1 :\ until X=&FF LDX &0355 :\ screen mode LDY LC3EF,X :\ text window right hand margin maximum STY &030A :\ text window right JSR LCA88 :\ calculate number of bytes in a line LDY LC3E7,X :\ text window bottom margin maximum STY &0309 :\ bottom margin LDY #&03 :\ Y=3 STY &0323 :\ set as last parameter INY :\ increment Y STY &0321 :\ set parameters DEC &0322 :\ DEC &0320 :\ JSR LCA39 :\ and do VDU 24 LDA #&F7 :\ JSR LC5A8 :\ clear bit 3 of &D0 LDX &0350 :\ window area start address lo LDA &0351 :\ window area start address hi .LC9F6 STX &034A :\ text cursor 6845 address STA &034B :\ text cursor 6845 address BPL LCA02 :\ set cursor position SEC :\ SBC &0354 :\ screen RAM size hi byte \**************** set cursor position ************************************ .LCA02 STX &D8 :\ set &D8/9 from X/A STA &D9 :\ LDX &034A :\ text cursor 6845 address LDA &034B :\ text cursor 6845 address LDY #&0E :\ Y=15 .LCA0E PHA :\ Push A LDA &0355 :\ screen mode CMP #&07 :\ is it mode 7? PLA :\ get back A BCS LCA27 :\ if mode 7 selected CA27 STX &DA :\ else store X LSR A :\ divide X/A by 8 ROR &DA :\ LSR A :\ ROR &DA :\ LSR A :\ ROR &DA :\ LDX &DA :\ JMP LCA2B :\ goto CA2B .LCA27 SBC #&74 :\ mode 7 subtract &74 EOR #&20 :\ EOR with &20 .LCA2B STY LFE00 :\ write to CRTC address file register STA LFE01 :\ and to relevant address (register 14) INY :\ Increment Y STY LFE00 :\ write to CRTC address file register STX LFE01 :\ and to relevant address (register 15) RTS :\ and RETURN \************************************************************************* \* * \* VDU 24 - DEFINE GRAPHICS WINDOW * \* * \* 8 parameters * \* * \************************************************************************* \&31C/D Left margin \&31E/F Bottom margin \&320/1 Right margin \&322/3 Top margin .LCA39 JSR LCA81 :\ exchange 310/3 with 328/3 LDX #&1C :\ LDY #&2C :\ JSR LD411 :\ calculate width=right - left :\ height = top-bottom ORA &032D :\ BMI LCA81 :\ exchange 310/3 with 328/3 and exit LDX #&20 :\ X=&20 JSR LD149 :\ scale pointers to mode LDX #&1C :\ X=&1C JSR LD149 :\ scale pointers to mode LDA &031F :\ check for negative margins ORA &031D :\ BMI LCA81 :\ if found exchange 310/3 with 328/3 and exit LDA &0323 :\ BNE LCA81 :\ exchange 310/3 with 328/3 and exit LDX &0355 :\ screen mode LDA &0321 :\ right margin hi STA &DA :\ store it LDA &0320 :\ right margin lo LSR &DA :\ /2 ROR A :\ A=A/2 LSR &DA :\ /2 BNE LCA81 :\ exchange 310/3 with 328/3 ROR A :\ A=A/2 LSR A :\ A=A/2 CMP LC3EF,X :\ text window right hand margin maximum BEQ LCA7A :\ if equal CA7A BPL LCA81 :\ exchange 310/3 with 328/3 .LCA7A LDY #&00 :\ Y=0 LDX #&1C :\ X=&1C JSR LD47C :\ set(300/7+Y) from (300/7+X) \***************** exchange 310/3 with 328/3 ***************************** .LCA81 LDX #&10 :\ X=10 LDY #&28 :\ Y=&28 JMP LCDE6 :\ exchange 300/3+Y and 300/3+X .LCA88 INY :\ Y=Y+1 TYA :\ A=Y LDY #&00 :\ Y=0 STY &034D :\ text window width hi (bytes) STA &034C :\ text window width lo (bytes) LDA &034F :\ bytes per character LSR A :\ /2 BEQ LCAA1 :\ if 0 exit .LCA98 ASL &034C :\ text window width lo (bytes) ROL &034D :\ text window width hi (bytes) LSR A :\ /2 BCC LCA98 :\ .LCAA1 RTS :\ \************************************************************************* \* * \* VDU 29 - SET GRAPHICS ORIGIN * \* * \* 4 parameters * \* * \************************************************************************* \ .LCAA2 LDX #&20 :\ LDY #&0C :\ JSR LD48A :\ (&300/3+Y)=(&300/3+X) JMP LD1B8 :\ set up external coordinates for graphics \************************************************************************* \* * \* VDU 127 (&7F) - DELETE (entry 32) * \* * \************************************************************************* .LCAAC JSR LC5C5 :\ cursor left JSR LC588 :\ A=0 if text cursor A=&20 if graphics cursor BNE LCAC7 :\ if graphics then CAC7 LDX &0360 :\ number of logical colours less 1 BEQ LCAC2 :\ if mode 7 CAC2 STA &DE :\ else store A (always 0) LDA #&C0 :\ A=&C0 STA &DF :\ store in &DF (&DE) now points to C300 SPACE pattern JMP LCFBF :\ display a space .LCAC2 LDA #&20 :\ A=&20 JMP LCFDC :\ and return to display a space .LCAC7 LDA #&7F :\ for graphics cursor JSR LD03E :\ set up character definition pointers LDX &035A :\ Background graphics colour LDY #&00 :\ Y=0 JMP LCF63 :\ invert pattern data (to background colour) \***** Add number of bytes in a line to X/A ****************************** .LCAD4 PHA :\ store A TXA :\ A=X CLC :\ clear carry ADC &0352 :\ bytes per character row TAX :\ X=A PLA :\ get back A ADC &0353 :\ bytes per character row RTS :\ and return \ \********* control scrolling in paged mode ******************************* .LCAE0 JSR LCB14 :\ zero paged mode line counter .LCAE3 JSR LE9D9 :\ osbyte 118 check keyboard status; set LEDs BCC LCAEA :\ if carry clear CAEA BMI LCAE0 :\ if M set CAE0 do it again .LCAEA LDA &D0 :\ VDU status byte EOR #&04 :\ invert bit 2 paged scrolling AND #&46 :\ and if 2 cursors, paged mode off, or scrolling BNE LCB1C :\ barred then CB1C to exit LDA &0269 :\ paged mode counter BMI LCB19 :\ if negative then exit via CB19 LDA &0319 :\ current text line CMP &0309 :\ bottom margin BCC LCB19 :\ increment line counter and exit LSR A :\ A=A/4 LSR A :\ SEC :\ set carry ADC &0269 :\ paged mode counter ADC &030B :\ top of text window CMP &0309 :\ bottom margin BCC LCB19 :\ increment line counter and exit CLC :\ clear carry .LCB0E JSR LE9D9 :\ osbyte 118 check keyboard status; set LEDs SEC :\ set carry BPL LCB0E :\ if +ve result then loop till shift pressed \**************** zero paged mode counter ******************************* .LCB14 LDA #&FF :\ STA &0269 :\ paged mode counter .LCB19 INC &0269 :\ paged mode counter .LCB1C RTS :\ \*********part of intitialisation routines ****************************** .LCB1D PHA :\ save A LDX #&7F :\ X=&7F LDA #&00 :\ A=0 STA &D0 :\ VDU status byte to set default conditions .LCB24 STA &02FF,X :\ zero 300,37E DEX :\ with this loop BNE LCB24 :\ JSR LCD07 :\ implode character definitions PLA :\ get back A LDX #&7F :\ X=&7F STX &0366 :\ mode 7 write cursor character .LCB33 BIT &028E :\ available RAM pages BMI LCB3A :\ if 32k CB3A ORA #&04 :\ ensure only modes 4-7 are available .LCB3A AND #&07 :\ X=A and 7 ensure legal mode TAX :\ X=mode STX &0355 :\ set screen mode flag LDA LC414,X :\ no. of colours -1 in mode table STA &0360 :\ number of logical colours less 1 LDA LC3FF,X :\ number of bytes /character for each mode STA &034F :\ bytes per character LDA LC43A,X :\ display mode pixels/byte table STA &0361 :\ pixels per byte BNE LCB56 :\ if <> 0 CB56 LDA #&07 :\ else A=7 .LCB56 ASL A :\ A=A*2 TAY :\ Y=A LDA LC406,Y :\ mask table STA &0363 :\ colour mask left .LCB5E ASL A :\ A=A*2 BPL LCB5E :\ If still +ve CB5E STA &0362 :\ colour mask right LDY LC440,X :\ screen display memory index table STY &0356 :\ memory map type LDA LC44F,Y :\ VDU section control JSR LE9F8 :\ set hardware scrolling to VIA LDA LC44B,Y :\ VDU section control JSR LE9F8 :\ set hardware scrolling to VIA LDA LC459,Y :\ Screen RAM size hi byte table STA &0354 :\ screen RAM size hi byte LDA LC45E,Y :\ screen ram address hi byte STA &034E :\ hi byte of screen RAM address TYA :\ Y=A ADC #&02 :\ Add 2 EOR #&07 :\ LSR A :\ /2 TAX :\ X=A LDA LC466,X :\ row multiplication table pointer STA &E0 :\ store it LDA #&C3 :\ A=&C3 STA &E1 :\ store it (&E0) now points to C3B5 or C375 LDA LC463,X :\ get nuber of bytes per row from table STA &0352 :\ store as bytes per character row STX &0353 :\ bytes per character row LDA #&43 :\ A=&43 JSR LC5A8 :\ A=A and &D0:&D0=A LDX &0355 :\ screen mode LDA LC3F7,X :\ get video ULA control setting JSR LEA00 :\ set video ULA using osbyte 154 PHP :\ push flags SEI :\ set interrupts LDX LC469,Y :\ get cursor end register data from table LDY #&0B :\ Y=11 .LCBB0 LDA LC46E,X :\ get end of 6845 registers 0-11 table JSR LC95E :\ set register Y DEX :\ reduce pointers DEY :\ BPL LCBB0 :\ and if still >0 do it again PLP :\ pull flags JSR LC839 :\ set default colours JSR LC9BD :\ set default windows .LCBC1 LDX #&00 :\ X=0 LDA &034E :\ hi byte of screen RAM address STX &0350 :\ window area start address lo STA &0351 :\ window area start address hi JSR LC9F6 :\ use X and Y to set new cursor address LDY #&0C :\ Y=12 JSR LCA2B :\ set registers 12 and 13 in CRTC LDA &0358 :\ background text colour LDX &0356 :\ memory map type LDY LC454,X :\ get section control number STY &035D :\ set it in jump vector lo LDY #&CC :\ Y=&CC STY &035E :\ upper byte of link address LDX #&00 :\ X=0 STX &0269 :\ paged mode counter STX &0318 :\ text column STX &0319 :\ current text line JMP (&035D) :\ jump vector set up previously \************************************************************************* \* * \* OSWORD 10 - READ CHARACTER DEFINITION * \* * \************************************************************************* \&EF=A, &F0=X, &F1=Y, on entry YX contains character number to be read \(&DE) points to address \on exit byte YX+1 to YX+8 contain definition JSR LD03E :\ set up character definition pointers LDY #&00 :\ Y=0 .LCBF8 LDA (&DE),Y :\ get first byte INY :\ Y=Y+1 STA (&F0),Y :\ store it in YX CPY #&08 :\ until Y=8 BNE LCBF8 :\ RTS :\ then exit \************************************************************************* \* * \* MAIN SCREEN CLEARANCE ROUTINE * \* * \************************************************************************* \on entry A contains background colour which is set in every byte \of the screen \************************ Mode 0,1,2 entry point ************************* STA &3000,X :\ STA &3100,X :\ STA &3200,X :\ STA &3300,X :\ STA &3400,X :\ STA &3500,X :\ STA &3600,X :\ STA &3700,X :\ STA &3800,X :\ STA &3900,X :\ STA &3A00,X :\ STA &3B00,X :\ STA &3C00,X :\ STA &3D00,X :\ STA &3E00,X :\ STA &3F00,X :\ \************************ Mode 3 entry point ***************************** STA &4000,X :\ STA &4100,X :\ STA &4200,X :\ STA &4300,X :\ STA &4400,X :\ STA &4500,X :\ STA &4600,X :\ STA &4700,X :\ STA &4800,X :\ STA &4900,X :\ STA &4A00,X :\ STA &4B00,X :\ STA &4C00,X :\ STA &4D00,X :\ STA &4E00,X :\ STA &4F00,X :\ STA &5000,X :\ STA &5100,X :\ STA &5200,X :\ STA &5300,X :\ STA &5400,X :\ STA &5500,X :\ STA &5600,X :\ STA &5700,X :\ \************************ Mode 4,5 entry point *************************** STA &5800,X :\ STA &5900,X :\ STA &5A00,X :\ STA &5B00,X :\ STA &5C00,X :\ STA &5D00,X :\ STA &5E00,X :\ STA &5F00,X :\ \************************ Mode 6 entry point ***************************** STA &6000,X :\ STA &6100,X :\ STA &6200,X :\ STA &6300,X :\ STA &6400,X :\ STA &6500,X :\ STA &6600,X :\ STA &6700,X :\ STA &6800,X :\ STA &6900,X :\ STA &6A00,X :\ STA &6B00,X :\ STA &6C00,X :\ STA &6D00,X :\ STA &6E00,X :\ STA &6F00,X :\ STA &7000,X :\ STA &7100,X :\ STA &7200,X :\ STA &7300,X :\ STA &7400,X :\ STA &7500,X :\ STA &7600,X :\ STA &7700,X :\ STA &7800,X :\ STA &7900,X :\ STA &7A00,X :\ STA &7B00,X :\ \************************ Mode 7 entry point ***************************** STA &7C00,X :\ STA &7D00,X :\ STA &7E00,X :\ STA &7F00,X :\ INX :\ BEQ LCD65 :\ exit .LCCF5 \****************** execute required function **************************** JMP (&035D) :\ jump vector set up previously \********* subtract bytes per line from X/A ****************************** .LCCF8 PHA :\ Push A TXA :\ A=X SEC :\ set carry for subtraction SBC &0352 :\ bytes per character row TAX :\ restore X PLA :\ and A SBC &0353 :\ bytes per character row CMP &034E :\ hi byte of screen RAM address .LCD06 RTS :\ return \************************************************************************* \* * \* OSBYTE 20 - EXPLODE CHARACTERS * \* * \************************************************************************* \ .LCD07 LDA #&0F :\ A=15 STA &0367 :\ font flag indicating that page &0C,&C0-&C2 are :\ used for user defined characters LDA #&0C :\ A=&0C LDY #&06 :\ set loop counter .LCD10 STA &0368,Y :\ set all font location bytes DEY :\ to page &0C to indicate only page available BPL LCD10 :\ for user character definitions CPX #&07 :\ is X= 7 or greater BCC LCD1C :\ if not CD1C LDX #&06 :\ else X=6 .LCD1C STX &0246 :\ character definition explosion switch LDA &0243 :\ A=primary OSHWM LDX #&00 :\ X=0 .LCD24 CPX &0246 :\ character definition explosion switch BCS LCD34 :\ LDY LC4BA,X :\ get soft character RAM allocation STA &0368,Y :\ font location bytes ADC #&01 :\ Add 1 INX :\ X=X+1 BNE LCD24 :\ if X<>0 then CD24 .LCD34 STA &0244 :\ current value of page (OSHWM) TAY :\ Y=A BEQ LCD06 :\ return via CD06 (ERROR?) LDX #&11 :\ X=&11 JMP LF168 :\ issue paged ROM service call &11 :\ font implosion/explosion warning \******** move text cursor to next line ********************************** .LCD3F LDA #&02 :\ A=2 to check if scrolling disabled BIT &D0 :\ VDU status byte BNE LCD47 :\ if scrolling is barred CD47 BVC LCD79 :\ if cursor editing mode disabled RETURN .LCD47 LDA &0309 :\ bottom margin BCC LCD4F :\ if carry clear on entry CD4F LDA &030B :\ else if carry set get top of text window .LCD4F BVS LCD59 :\ and if cursor editing enabled CD59 STA &0319 :\ get current text line PLA :\ pull return link from stack PLA :\ JMP LC6AF :\ set up cursor and display address .LCD59 PHP :\ push flags CMP &0365 :\ Y coordinate of text input cursor BEQ LCD78 :\ if A=line count of text input cursor CD78 to exit PLP :\ get back flags BCC LCD66 :\ DEC &0365 :\ Y coordinate of text input cursor .LCD65 RTS :\ exit .LCD66 \ INC &0365 :\ Y coordinate of text input cursor RTS :\ exit \*********************** set up write cursor ******************************** .LCD6A PHP :\ save flags PHA :\ save A LDY &034F :\ bytes per character DEY :\ Y=Y-1 BNE LCD8F :\ if Y=0 Mode 7 is in use LDA &0338 :\ so get mode 7 write character cursor character &7F STA (&D8),Y :\ store it at top scan line of current character .LCD77 PLA :\ pull A .LCD78 PLP :\ pull flags .LCD79 RTS :\ and exit .LCD7A \ PHP :\ push flags PHA :\ push A LDY &034F :\ bytes per character DEY :\ BNE LCD8F :\ if not mode 7 LDA (&D8),Y :\ get cursor from top scan line STA &0338 :\ store it LDA &0366 :\ mode 7 write cursor character STA (&D8),Y :\ store it at scan line JMP LCD77 :\ and exit .LCD8F LDA #&FF :\ A=&FF =cursor CPY #&1F :\ except in mode 2 (Y=&1F) BNE LCD97 :\ if not CD97 LDA #&3F :\ load cursor byte mask \********** produce white block write cursor ***************************** .LCD97 STA &DA :\ store it .LCD99 LDA (&D8),Y :\ get scan line byte EOR &DA :\ invert it STA (&D8),Y :\ store it on scan line DEY :\ decrement scan line counter BPL LCD99 :\ do it again BMI LCD77 :\ then jump to &CD77 .LCDA4 JSR LCE5B :\ exchange line and column cursors with workspace copies LDA &0309 :\ bottom margin STA &0319 :\ current text line JSR LCF06 :\ set up display address .LCDB0 JSR LCCF8 :\ subtract bytes per character row from this BCS LCDB8 :\ wraparound if necessary ADC &0354 :\ screen RAM size hi byte .LCDB8 STA &DB :\ store A STX &DA :\ X STA &DC :\ A again BCS LCDC6 :\ if C set there was no wraparound so CDC6 .LCDC0 JSR LCE73 :\ copy line to new position \ :\ using (&DA) for read \ :\ and (&D8) for write JMP LCDCE :\ .LCDC6 JSR LCCF8 :\ subtract bytes per character row from X/A BCC LCDC0 :\ if a result is outside screen RAM CDC0 JSR LCE38 :\ perform a copy .LCDCE LDA &DC :\ set write pointer from read pointer LDX &DA :\ STA &D9 :\ STX &D8 :\ DEC &DE :\ decrement window height BNE LCDB0 :\ and if not zero CDB0 .LCDDA LDX #&28 :\ point to workspace LDY #&18 :\ point to text column/line .LCDDE LDA #&02 :\ number of bytes to swap BNE LCDE8 :\ exchange (328/9)+Y with (318/9)+X .LCDE2 LDX #&24 :\ point to graphics cursor .LCDE4 LDY #&14 :\ point to last graphics cursor .LCDE6 \ :\ A=4 to swap X and Y coordinates \*************** exchange 300/3+Y with 300/3+X *************************** LDA #&04 :\ A =4 .LCDE8 \************** exchange (300/300+A)+Y with (300/300+A)+X ***************** STA &DA :\ store it as loop counter .LCDEA LDA &0300,X :\ get byte PHA :\ store it LDA &0300,Y :\ get byte pointed to by Y STA &0300,X :\ put it in 300+X PLA :\ get back A STA &0300,Y :\ put it in 300+Y INX :\ increment pointers INY :\ DEC &DA :\ decrement loop counter BNE LCDEA :\ and if not 0 do it again RTS :\ and exit \******** execute upward scroll ****************************************** .LCDFF \ JSR LCE5B :\ exchange line and column cursors with workspace copies LDY &030B :\ top of text window STY &0319 :\ current text line JSR LCF06 :\ set up display address .LCE0B JSR LCAD4 :\ add bytes per char. row BPL LCE14 :\ SEC :\ SBC &0354 :\ screen RAM size hi byte .LCE14 STA &DB :\ (&DA)=X/A STX &DA :\ STA &DC :\ &DC=A BCC LCE22 :\ .LCE1C JSR LCE73 :\ copy line to new position :\ using (&DA) for read :\ and (&D8) for write JMP LCE2A :\ exit .LCE22 JSR LCAD4 :\ add bytes per char. row BMI LCE1C :\ if outside screen RAM CE1C JSR LCE38 :\ perform a copy .LCE2A LDA &DC :\ LDX &DA :\ STA &D9 :\ STX &D8 :\ DEC &DE :\ decrement window height BNE LCE0B :\ CE0B if not 0 BEQ LCDDA :\ exchange text column/linelse CDDA \*********** copy routines *********************************************** .LCE38 LDX &034D :\ text window width hi (bytes) BEQ LCE4D :\ if no more than 256 bytes to copy X=0 so CE4D LDY #&00 :\ Y=0 to set loop counter .LCE3F LDA (&DA),Y :\ copy 256 bytes STA (&D8),Y :\ INY :\ BNE LCE3F :\ Till Y=0 again INC &D9 :\ increment hi bytes INC &DB :\ DEX :\ decrement window width BNE LCE3F :\ if not 0 go back and do loop again .LCE4D LDY &034C :\ text window width lo (bytes) BEQ LCE5A :\ if Y=0 CE5A .LCE52 DEY :\ else Y=Y-1 LDA (&DA),Y :\ copy Y bytes STA (&D8),Y :\ TYA :\ A=Y BNE LCE52 :\ if not 0 CE52 .LCE5A RTS :\ and exit .LCE5B JSR LCDDA :\ exchange text column/line with workspace SEC :\ set carry LDA &0309 :\ bottom margin SBC &030B :\ top of text window STA &DE :\ store it BNE LCE6E :\ set text column to left hand column PLA :\ get back return address PLA :\ JMP LCDDA :\ exchange text column/line with workspace .LCE6E LDA &0308 :\ text window left BPL LCEE3 :\ Jump CEE3 always! .LCE73 LDA &DA :\ get back A PHA :\ push A SEC :\ set carry LDA &030A :\ text window right SBC &0308 :\ text window left STA &DF :\ .LCE7F LDY &034F :\ bytes per character to set loop counter DEY :\ copy loop .LCE83 LDA (&DA),Y :\ STA (&D8),Y :\ DEY :\ BPL LCE83 :\ LDX #&02 :\ X=2 .LCE8C CLC :\ clear carry LDA &D8,X :\ ADC &034F :\ bytes per character STA &D8,X :\ LDA &D9,X :\ ADC #&00 :\ BPL LCE9E :\ if this remains in screen RAM OK SEC :\ else wrap around screen SBC &0354 :\ screen RAM size hi byte .LCE9E STA &D9,X :\ DEX :\ X=X-2 DEX :\ BEQ LCE8C :\ if X=0 adjust second set of pointers DEC &DF :\ decrement window width BPL LCE7F :\ and if still +ve do it all again PLA :\ get back A STA &DA :\ and store it RTS :\ then exit \*********** clear a line ************************************************ .LCEAC LDA &0318 :\ text column PHA :\ save it JSR LCE6E :\ set text column to left hand column JSR LCF06 :\ set up display address SEC :\ set carry LDA &030A :\ text window right SBC &0308 :\ text window left STA &DC :\ as window width .LCEBF LDA &0358 :\ background text colour LDY &034F :\ bytes per character .LCEC5 DEY :\ Y=Y-1 decrementing loop counter STA (&D8),Y :\ store background colour at this point on screen BNE LCEC5 :\ if Y<>0 do it again TXA :\ else A=X CLC :\ clear carry to add ADC &034F :\ bytes per character TAX :\ X=A restoring it LDA &D9 :\ get hi byte ADC #&00 :\ Add carry if any BPL LCEDA :\ if +ve CeDA SEC :\ else wrap around SBC &0354 :\ screen RAM size hi byte .LCEDA STX &D8 :\ restore D8/9 STA &D9 :\ DEC &DC :\ decrement window width BPL LCEBF :\ ind if not 0 do it all again PLA :\ get back A .LCEE3 STA &0318 :\ restore text column .LCEE6 SEC :\ set carry RTS :\ and exit .LCEE8 LDX &0318 :\ text column CPX &0308 :\ text window left BMI LCEE6 :\ if less than left margin return with carry set CPX &030A :\ text window right BEQ LCEF7 :\ if equal to right margin thats OK BPL LCEE6 :\ if greater than right margin return with carry set .LCEF7 LDX &0319 :\ current text line CPX &030B :\ top of text window BMI LCEE6 :\ if less than top margin CPX &0309 :\ bottom margin BEQ LCF06 :\ set up display address BPL LCEE6 :\ or greater than bottom margin return with carry set \************ set up display address ************************************* .LCF06 \Mode 0 (0319)*640+(0318)* 8 \Mode 1 (0319)*640+(0318)*16 \Mode 2 (0319)*640+(0318)*32 \Mode 3 (0319)*640+(0318)* 8 \Mode 4 (0319)*320+(0318)* 8 \Mode 5 (0319)*320+(0318)*16 \Mode 6 (0319)*320+(0318)* 8 \Mode 7 (0319)* 40+(0318) \ \this gives a displacement relative to the screen RAM start address \which is added to the calculated number and stored in in 34A/B \if the result is less than &8000, the top of screen RAM it is copied into X/A \and D8/9. \if the result is greater than &7FFF the hi byte of screen RAM size is \subtracted to wraparound the screen. X/A, D8/9 are then set from this LDA &0319 :\ current text line ASL A :\ A=A*2 TAY :\ Y=A LDA (&E0),Y :\ get CRTC multiplication table pointer STA &D9 :\ &D9=A INY :\ Y=Y+1 LDA #&02 :\ A=2 AND &0356 :\ memory map type PHP :\ save flags LDA (&E0),Y :\ get CRTC multiplication table pointer PLP :\ pull flags BEQ LCF1E :\ LSR &D9 :\ &D9=&D9/2 ROR A :\ A=A/2 +(128*carry) .LCF1E ADC &0350 :\ window area start address lo STA &D8 :\ store it LDA &D9 :\ ADC &0351 :\ window area start address hi TAY :\ LDA &0318 :\ text column LDX &034F :\ bytes per character DEX :\ X=X-1 BEQ LCF44 :\ if X=0 mode 7 CF44 CPX #&0F :\ is it mode 1 or mode 5? BEQ LCF39 :\ yes CF39 with carry set BCC LCF3A :\ if its less (mode 0,3,4,6) CF3A ASL A :\ A=A*16 if entered here (mode 2) .LCF39 ASL A :\ A=A*8 if entered here .LCF3A ASL A :\ A=A*4 if entered here ASL A :\ BCC LCF40 :\ if carry clear INY :\ Y=Y+2 INY :\ .LCF40 ASL A :\ A=A*2 BCC LCF45 :\ if carry clear add to &D8 INY :\ if not Y=Y+1 .LCF44 CLC :\ clear carry .LCF45 ADC &D8 :\ add to &D8 STA &D8 :\ and store it STA &034A :\ text cursor 6845 address TAX :\ X=A TYA :\ A=Y ADC #&00 :\ Add carry if set STA &034B :\ text cursor 6845 address BPL LCF59 :\ if less than &800 goto &CF59 SEC :\ else wrap around SBC &0354 :\ screen RAM size hi byte .LCF59 STA &D9 :\ store in high byte CLC :\ clear carry RTS :\ and exit \******** Graphics cursor display routine ******************************** .LCF5D LDX &0359 :\ foreground graphics colour LDY &035B :\ foreground graphics plot mode (GCOL n) .LCF63 JSR LD0B3 :\ set graphics byte mask in &D4/5 JSR LD486 :\ copy (324/7) graphics cursor to workspace (328/B) LDY #&00 :\ Y=0 .LCF6B STY &DC :\ &DC=Y LDY &DC :\ Y=&DC LDA (&DE),Y :\ get pattern byte BEQ LCF86 :\ if A=0 CF86 STA &DD :\ else &DD=A .LCF75 BPL LCF7A :\ and if >0 CF7A JSR LD0E3 :\ else display a pixel .LCF7A INC &0324 :\ current horizontal graphics cursor BNE LCF82 :\ INC &0325 :\ current horizontal graphics cursor .LCF82 ASL &DD :\ &DD=&DD*2 BNE LCF75 :\ and if<>0 CF75 .LCF86 LDX #&28 :\ point to workspace LDY #&24 :\ point to horizontal graphics cursor JSR LD482 :\ 0300/1+Y=0300/1+X LDY &0326 :\ current vertical graphics cursor BNE LCF95 :\ DEC &0327 :\ current vertical graphics cursor .LCF95 DEC &0326 :\ current vertical graphics cursor LDY &DC :\ INY :\ CPY #&08 :\ if Y<8 then do loop again BNE LCF6B :\ else LDX #&28 :\ point to workspace LDY #&24 :\ point to graphics cursor JMP LD48A :\ (&300/3+Y)=(&300/3+X) \*********** home graphics cursor *************************************** .LCFA6 LDX #&06 :\ point to graphics window TOP LDY #&26 :\ point to workspace JSR LD482 :\ 0300/1+Y=0300/1+X \************* set graphics cursor to left hand column ******************* .LCFAD LDX #&00 :\ X=0 point to graphics window left LDY #&24 :\ Y=&24 JSR LD482 :\ 0300/1+Y=0300/1+X JMP LD1B8 :\ set up external coordinates for graphics .LCFB7 LDX &0360 :\ number of logical colours less 1 BEQ LCFDC :\ if MODE 7 CFDC JSR LD03E :\ set up character definition pointers .LCFBF LDX &0360 :\ number of logical colours less 1 LDA &D0 :\ VDU status byte AND #&20 :\ and out bit 5 printing at graphics cursor BNE LCF5D :\ if set CF5D LDY #&07 :\ else Y=7 CPX #&03 :\ if X=3 BEQ LCFEE :\ goto CFEE to handle 4 colour modes BCS LD01E :\ else if X>3 D01E to deal with 16 colours .LCFD0 LDA (&DE),Y :\ get pattern byte ORA &D2 :\ text colour byte to be orred or EORed into memory EOR &D3 :\ text colour byte to be orred or EORed into memory STA (&D8),Y :\ write to screen DEY :\ Y=Y-1 BPL LCFD0 :\ if still +ve do loop again RTS :\ and exit \******* convert teletext characters ************************************* \mode 7 .LCFDC LDY #&02 :\ Y=2 .LCFDE CMP LC4B6,Y :\ compare with teletext conversion table BEQ LCFE9 :\ if equal then CFE9 DEY :\ else Y=Y-1 BPL LCFDE :\ and if +ve CFDE .LCFE6 STA (&D8,X) :\ if not write byte to screen RTS :\ and exit .LCFE9 LDA LC4B7,Y :\ convert with teletext conversion table BNE LCFE6 :\ and write it \***********four colour modes ******************************************** .LCFEE LDA (&DE),Y :\ get pattern byte PHA :\ save it LSR A :\ move hi nybble to lo LSR A :\ LSR A :\ LSR A :\ TAX :\ X=A LDA LC31F,X :\ 4 colour mode byte mask look up table ORA &D2 :\ text colour byte to be orred or EORed into memory EOR &D3 :\ text colour byte to be orred or EORed into memory STA (&D8),Y :\ write to screen TYA :\ A=Y CLC :\ clear carry ADC #&08 :\ add 8 to move screen RAM pointer 8 bytes TAY :\ Y=A PLA :\ get back A AND #&0F :\ clear high nybble TAX :\ X=A LDA LC31F,X :\ 4 colour mode byte mask look up table ORA &D2 :\ text colour byte to be orred or EORed into memory EOR &D3 :\ text colour byte to be orred or EORed into memory STA (&D8),Y :\ write to screen TYA :\ A=Y SBC #&08 :\ A=A-9 TAY :\ Y=A BPL LCFEE :\ if +ve do loop again .LD017 RTS :\ exit .LD018 TYA :\ Y=Y-&21 SBC #&21 :\ BMI LD017 :\ IF Y IS negative then RETURN TAY :\ else A=Y \******* 16 COLOUR MODES ************************************************* .LD01E LDA (&DE),Y :\ get pattern byte STA &DC :\ store it SEC :\ set carry .LD023 LDA #&00 :\ A=0 ROL &DC :\ carry now occupies bit 0 of DC BEQ LD018 :\ when DC=0 again D018 to deal with next pattern byte ROL A :\ get bit 7 from &DC into A bit 0 ASL &DC :\ rotate again to get second ROL A :\ bit into A TAX :\ and store result in X LDA LC32F,X :\ multiply by &55 using look up table ORA &D2 :\ and set colour factors EOR &D3 :\ STA (&D8),Y :\ and store result CLC :\ clear carry TYA :\ Y=Y+8 moving screen RAM pointer on 8 bytes ADC #&08 :\ TAY :\ BCC LD023 :\ iloop to D023 to deal with next bit pair \************* calculate pattern address for given code ****************** \A contains code on entry = 12345678 .LD03E ASL A :\ 23456780 C holds 1 ROL A :\ 34567801 C holds 2 ROL A :\ 45678012 C holds 3 STA &DE :\ save this pattern AND #&03 :\ 00000012 ROL A :\ 00000123 C=0 TAX :\ X=A=0 - 7 AND #&03 :\ A=00000023 ADC #&BF :\ A=&BF,C0 or C1 TAY :\ this is used as a pointer LDA LC40D,X :\ A=&80/2^X i.e.1,2,4,8,&10,&20,&40, or &80 BIT &0367 :\ with font flag BEQ LD057 :\ if 0 D057 LDY &0367,X :\ else get hi byte from table .LD057 STY &DF :\ store Y LDA &DE :\ get back pattern AND #&F8 :\ convert to 45678000 STA &DE :\ and re store it RTS :\ exit \************************************************************************* \************************************************************************* \** ** \** ** \** PLOT ROUTINES ENTER HERE ** \** ** \** ** \************************************************************************* \************************************************************************* \on entry ADDRESS PARAMETER DESCRIPTION \ 031F 1 plot type \ 0320/1 2,3 X coordinate \ 0322/3 4,5 Y coordinate .LD060 LDX #&20 :\ X=&20 JSR LD14D :\ translate coordinates LDA &031F :\ get plot type CMP #&04 :\ if its 4 BEQ LD0D9 :\ D0D9 move absolute LDY #&05 :\ Y=5 AND #&03 :\ mask only bits 0 and 1 BEQ LD080 :\ if result is 0 then its a move (multiple of 8) LSR A :\ else move bit 0 int C BCS LD078 :\ if set then D078 graphics colour required DEY :\ Y=4 BNE LD080 :\ logic inverse colour must be wanted \******** graphics colour wanted ***************************************** .LD078 TAX :\ X=A if A=0 its a foreground colour 1 its background LDY &035B,X :\ get fore or background graphics PLOT mode LDA &0359,X :\ get fore or background graphics colour TAX :\ X=A .LD080 JSR LD0B3 :\ set up colour masks in D4/5 LDA &031F :\ get plot type BMI LD0AB :\ if &80-&FF then D0AB type not implemented ASL A :\ bit 7=bit 6 BPL LD0C6 :\ if bit 6 is 0 then plot type is 0-63 so D0C6 AND #&F0 :\ else mask out lower nybble ASL A :\ shift old bit 6 into C bit old 5 into bit 7 BEQ LD0D6 :\ if 0 then type 64-71 was called single point plot :\ goto D0D6 EOR #&40 :\ if bit 6 NOT set type &80-&87 fill triangle BEQ LD0A8 :\ so D0A8 PHA :\ else push A JSR LD0DC :\ copy 0320/3 to 0324/7 setting XY in current graphics :\ coordinates PLA :\ get back A EOR #&60 :\ if BITS 6 and 5 NOT SET type 72-79 lateral fill BEQ LD0AE :\ so D0AE CMP #&40 :\ if type 88-95 horizontal line blanking BNE LD0AB :\ so D0AB LDA #&02 :\ else A=2 STA &DC :\ store it JMP LD506 :\ and jump to D506 type not implemented .LD0A8 JMP LD5EA :\ to fill triangle routine .LD0AB JMP LC938 :\ VDU extension access entry .LD0AE STA &DC :\ store A JMP LD4BF :\ \********* set colour masks ********************************************** \graphics mode in Y \colour in X .LD0B3 TXA :\ A=X ORA LC41C,Y :\ or with GCOL plot options table byte EOR LC41D,Y :\ EOR with following byte STA &D4 :\ and store it TXA :\ A=X ORA LC41B,Y :\ EOR LC420,Y :\ STA &D5 :\ RTS :\ exit with masks in &D4/5 \************** analyse first parameter in 0-63 range ******************** \ :\ .LD0C6 ASL A :\ shift left again BMI LD0AB :\ if -ve options are in range 32-63 not implemented ASL A :\ shift left twice more ASL A :\ BPL LD0D0 :\ if still +ve type is 0-7 or 16-23 so D0D0 JSR LD0EB :\ else display a point .LD0D0 JSR LD1ED :\ perform calculations JMP LD0D9 :\ \************************************************************************* \* * \* PLOT A SINGLE POINT * \* * \************************************************************************* .LD0D6 JSR LD0EB :\ display a point .LD0D9 JSR LCDE2 :\ swap current and last graphics position .LD0DC LDY #&24 :\ Y=&24 .LD0DE LDX #&20 :\ X=&20 JMP LD48A :\ copy parameters to 324/7 (300/3 +Y) .LD0E3 LDX #&24 :\ JSR LD85F :\ calculate position BEQ LD0F0 :\ if result =0 then D0F0 RTS :\ else exit .LD0EB :\ JSR LD85D :\ calculate position BNE LD103 :\ if A<>0 D103 and return .LD0F0 LDY &031A :\ else get current graphics scan line .LD0F3 LDA &D1 :\ pick up and modify screen byte AND &D4 :\ ORA (&D6),Y :\ STA &DA :\ LDA &D5 :\ AND &D1 :\ EOR &DA :\ STA (&D6),Y :\ put it back again .LD103 RTS :\ and exit .LD104 LDA (&D6),Y :\ this is a more simplistic version of the above ORA &D4 :\ EOR &D5 :\ STA (&D6),Y :\ RTS :\ and exit \************************** Check window limits ************************* \ :\ .LD10D LDX #&24 :\ X=&24 .LD10F LDY #&00 :\ Y=0 STY &DA :\ &DA=0 LDY #&02 :\ Y=2 JSR LD128 :\ check vertical graphics position 326/7 :\ bottom and top margins 302/3, 306/7 ASL &DA :\ DATA is set in &DA bits 0 and 1 then shift left ASL &DA :\ twice to make room for next pass DEX :\ X=&22 DEX :\ LDY #&00 :\ Y=0 JSR LD128 :\ left and right margins 300/1, 304/5 :\ cursor horizontal position 324/5 INX :\ X=X+2 INX :\ LDA &DA :\ A=&DA RTS :\ exit \*** cursor and margins check ****************************************** :\ .LD128 LDA &0302,X :\ check for window violation CMP &0300,Y :\ 300/1 +Y > 302/3+X LDA &0303,X :\ then window fault SBC &0301,Y :\ BMI LD146 :\ so D146 LDA &0304,Y :\ check other windows CMP &0302,X :\ LDA &0305,Y :\ SBC &0303,X :\ BPL LD148 :\ if no violation exit INC &DA :\ else DA=DA+1 .LD146 INC &DA :\ DA=DA+1 .LD148 RTS :\ and exit DA=0 no problems DA=1 first check 2, 2nd \***********set up and adjust positional data **************************** .LD149 LDA #&FF :\ A=&FF BNE LD150 :\ then &D150 .LD14D LDA &031F :\ get first parameter in plot .LD150 STA &DA :\ store in &DA LDY #&02 :\ Y=2 JSR LD176 :\ set up vertical coordinates/2 JSR LD1AD :\ /2 again to convert 1023 to 0-255 for internal use :\ this is why minimum vertical plot separation is 4 LDY #&00 :\ Y=0 DEX :\ X=x-2 DEX :\ JSR LD176 :\ set up horiz. coordinates/2 this is OK for mode0,4 LDY &0361 :\ get number of pixels/byte (-1) CPY #&03 :\ if Y=3 (modes 1 and 5) BEQ LD16D :\ D16D BCS LD170 :\ for modes 0 & 4 this is 7 so D170 JSR LD1AD :\ for other modes divide by 2 twice .LD16D JSR LD1AD :\ divide by 2 .LD170 LDA &0356 :\ get screen display type BNE LD1AD :\ if not 0 (modes 3-7) divide by 2 again RTS :\ and exit \for mode 0 1 division 1280 becomes 640 = horizontal resolution \for mode 1 2 divisions 1280 becomes 320 = horizontal resolution \for mode 2 3 divisions 1280 becomes 160 = horizontal resolution \for mode 4 2 divisions 1280 becomes 320 = horizontal resolution \for mode 5 3 divisions 1280 becomes 160 = horizontal resolution \********** calculate external coordinates in internal format *********** \on entry X is usually &1E or &20 .LD176 CLC :\ clear carry LDA &DA :\ get &DA AND #&04 :\ if bit 2=0 BEQ LD186 :\ then D186 to calculate relative coordinates LDA &0302,X :\ else get coordinate PHA :\ LDA &0303,X :\ BCC LD194 :\ and goto D194 .LD186 LDA &0302,X :\ get coordinate ADC &0310,Y :\ add cursor position PHA :\ save it LDA &0303,X :\ ADC &0311,Y :\ add cursor CLC :\ clear carry .LD194 STA &0311,Y :\ save new cursor ADC &030D,Y :\ add graphics origin STA &0303,X :\ store it PLA :\ get back lo byte STA &0310,Y :\ save it in new cursor lo CLC :\ clear carry ADC &030C,Y :\ add to graphics orgin STA &0302,X :\ store it BCC LD1AD :\ if carry set INC &0303,X :\ increment hi byte as you would expect! .LD1AD LDA &0303,X :\ get hi byte ASL A :\ ROR &0303,X :\ divide by 2 ROR &0302,X :\ RTS :\ and exit \***** calculate external coordinates from internal coordinates************ .LD1B8 LDY #&10 :\ Y=10 JSR LD488 :\ copy 324/7 to 310/3 i.e.current graphics cursor \ :\ position to position in external values LDX #&02 :\ X=2 LDY #&02 :\ Y=2 JSR LD1D5 :\ multiply 312/3 by 4 and subtract graphics origin LDX #&00 :\ X=0 LDY #&04 :\ Y=4 LDA &0361 :\ get number of pixels/byte .LD1CB DEY :\ Y=Y-1 LSR A :\ divide by 2 BNE LD1CB :\ if result not 0 D1CB LDA &0356 :\ else get screen display type BEQ LD1D5 :\ and if 0 D1D5 INY :\ .LD1D5 ASL &0310,X :\ multiply coordinate by 2 ROL &0311,X :\ DEY :\ Y-Y-1 BNE LD1D5 :\ and if Y<>0 do it again SEC :\ set carry JSR LD1E3 :\ INX :\ increment X .LD1E3 LDA &0310,X :\ get current graphics position in external coordinates SBC &030C,X :\ subtract origin STA &0310,X :\ store in graphics position RTS :\ and exit \************* compare X and Y PLOT spans ******************************** .LD1ED JSR LD40D :\ Set X and Y spans in workspace 328/9 32A/B LDA &032B :\ compare spans EOR &0329 :\ if result -ve spans are different in sign so BMI LD207 :\ goto D207 LDA &032A :\ else A=hi byte of difference in spans CMP &0328 :\ LDA &032B :\ SBC &0329 :\ JMP LD214 :\ and goto D214 .LD207 LDA &0328 :\ A = hi byte of SUM of spans CLC :\ ADC &032A :\ LDA &0329 :\ ADC &032B :\ .LD214 ROR A :\ A=A/2 LDX #&00 :\ X=0 EOR &032B :\ BPL LD21E :\ if positive result D21E LDX #&02 :\ else X=2 .LD21E STX &DE :\ store it LDA LC4AA,X :\ set up vector address STA &035D :\ in 35D LDA LC4AB,X :\ STA &035E :\ and 35E LDA &0329,X :\ get hi byte of span BPL LD235 :\ if +ve D235 LDX #&24 :\ X=&24 BNE LD237 :\ jump to D237 .LD235 LDX #&20 :\ X=&20 .LD237 STX &DF :\ store it LDY #&2C :\ Y=&2C JSR LD48A :\ get X coordinate data or horizontal coord of :\ curent graphics cursor LDA &DF :\ get back original X EOR #&04 :\ covert &20 to &24 and vice versa STA &DD :\ ORA &DE :\ TAX :\ JSR LD480 :\ copy 330/1 to 300/1+X LDA &031F :\ get plot type AND #&10 :\ check bit 4 ASL A :\ ASL A :\ ASL A :\ move to bit 7 STA &DB :\ store it LDX #&2C :\ X=&2C JSR LD10F :\ check for window violations STA &DC :\ BEQ LD263 :\ if none then D263 LDA #&40 :\ else set bit 6 of &DB ORA &DB :\ STA &DB :\ .LD263 LDX &DD :\ JSR LD10F :\ check window violations again BIT &DC :\ if bit 7 of &DC NOT set BEQ LD26D :\ D26D RTS :\ else exit .LD26D LDX &DE :\ X=&DE BEQ LD273 :\ if X=0 D273 LSR A :\ A=A/2 LSR A :\ A=A/2 .LD273 AND #&02 :\ clear all but bit 2 BEQ LD27E :\ if bit 2 set D27E TXA :\ else A=X ORA #&04 :\ A=A or 4 setting bit 3 TAX :\ X=A JSR LD480 :\ set 300/1+x to 330/1 .LD27E JSR LD42C :\ more calcualtions LDA &DE :\ A=&DE EOR 2 EOR #&02 :\ TAX :\ X=A TAY :\ Y=A LDA &0329 :\ compare upper byte of spans EOR &032B :\ BPL LD290 :\ if signs are the same D290 INX :\ else X=X+1 .LD290 LDA LC4AE,X :\ get vector addresses and store 332/3 STA &0332 :\ LDA LC4B2,X :\ STA &0333 :\ LDA #&7F :\ A=&7F STA &0334 :\ store it BIT &DB :\ if bit 6 set BVS LD2CE :\ the D2CE LDA LC447,X :\ get VDU section number TAX :\ X=A SEC :\ set carry LDA &0300,X :\ subtract coordinates SBC &032C,Y :\ STA &DA :\ LDA &0301,X :\ SBC &032D,Y :\ LDY &DA :\ Y=hi TAX :\ X=lo=A BPL LD2C0 :\ and if A+Ve D2C0 JSR LD49B :\ negate Y/A .LD2C0 TAX :\ X=A increment Y/A INY :\ Y=Y+1 BNE LD2C5 :\ INX :\ X=X+1 .LD2C5 TXA :\ A=X BEQ LD2CA :\ if A=0 D2CA LDY #&00 :\ else Y=0 .LD2CA STY &DF :\ &DF=Y BEQ LD2D7 :\ if 0 then D2D7 .LD2CE TXA :\ A=X LSR A :\ A=A/4 ROR A :\ ORA #&02 :\ bit 1 set EOR &DE :\ STA &DE :\ and store .LD2D7 LDX #&2C :\ X=&2C JSR LD864 :\ LDX &DC :\ BNE LD2E2 :\ DEC &DD :\ .LD2E2 DEX :\ X=X-1 .LD2E3 LDA &DB :\ A=&3B BEQ LD306 :\ if 0 D306 BPL LD2F9 :\ else if +ve D2F9 BIT &0334 :\ BPL LD2F3 :\ if bit 7=0 D2F3 DEC &0334 :\ else decrement BNE LD316 :\ and if not 0 D316 .LD2F3 INC &0334 :\ ASL A :\ A=A*2 BPL LD306 :\ if +ve D306 .LD2F9 STX &DC :\ LDX #&2C :\ JSR LD85F :\ calcualte screen position LDX &DC :\ get back original X ORA #&00 :\ BNE LD316 :\ .LD306 LDA &D1 :\ byte mask for current graphics point AND &D4 :\ and with graphics colour byte ORA (&D6),Y :\ or with curent graphics cell line STA &DA :\ store result LDA &D5 :\ same again with next byte (hi??) AND &D1 :\ EOR &DA :\ STA (&D6),Y :\ then store it inm current graphics line .LD316 SEC :\ set carry LDA &0335 :\ A=&335/6-&337/8 SBC &0337 :\ STA &0335 :\ LDA &0336 :\ SBC &0338 :\ BCS LD339 :\ if carry set D339 STA &DA :\ LDA &0335 :\ ADC &0339 :\ STA &0335 :\ LDA &DA :\ ADC &033A :\ CLC :\ .LD339 STA &0336 :\ PHP :\ BCS LD348 :\ if carry clear jump to VDU routine else D348 JMP (&0332) :\ \****** vertical scan module 1****************************************** DEY :\ Y=Y-1 BPL LD348 :\ if + D348 JSR LD3D3 :\ else d3d3 to advance pointers .LD348 JMP (&035D) :\ and JUMP (&35D) \****** vertical scan module 2****************************************** INY :\ Y=Y+1 CPY #&08 :\ if Y<>8 BNE LD348 :\ then D348 CLC :\ else clear carry LDA &D6 :\ get address of top line of cuirrent graphics cell ADC &0352 :\ add number of bytes/character row STA &D6 :\ store it LDA &D7 :\ do same for hibyte ADC &0353 :\ BPL LD363 :\ if result -ve then we are above screen RAM SEC :\ so SBC &0354 :\ subtract screen memory size hi .LD363 STA &D7 :\ store it this wraps around point to screen RAM LDY #&00 :\ Y=0 JMP (&035D) :\ \****** horizontal scan module 1****************************************** LSR &D1 :\ shift byte mask BCC LD348 :\ if carry clear (&D1 was +ve) goto D348 JSR LD3ED :\ else reset pointers JMP (&035D) :\ and off to do more \****** horizontal scan module 2****************************************** ASL &D1 :\ shift byte mask BCC LD348 :\ if carry clear (&D1 was +ve) goto D348 JSR LD3FD :\ else reset pointers JMP (&035D) :\ and off to do more DEY :\ Y=Y-1 BPL LD38D :\ if +ve D38D JSR LD3D3 :\ advance pointers BNE LD38D :\ goto D38D normally LSR &D1 :\ shift byte mask BCC LD38D :\ if carry clear (&D1 was +ve) goto D348 JSR LD3ED :\ else reset pointers .LD38D PLP :\ pull flags INX :\ X=X+1 BNE LD395 :\ if X>0 D395 INC &DD :\ else increment &DD BEQ LD39F :\ and if not 0 D39F .LD395 BIT &DB :\ else if BIT 6 = 1 BVS LD3A0 :\ goto D3A0 BCS LD3D0 :\ if BIT 7=1 D3D0 DEC &DF :\ else Decrement &DF BNE LD3D0 :\ and if not Zero D3D0 .LD39F RTS :\ else return .LD3A0 LDA &DE :\ A=&DE STX &DC :\ &DC=X AND #&02 :\ clear all but bit 1 TAX :\ X=A BCS LD3C2 :\ and if carry set goto D3C2 BIT &DE :\ if Bit 7 of &DE =1 BMI LD3B7 :\ then D3B7 INC &032C,X :\ else increment BNE LD3C2 :\ and if not 0 D3C2 INC &032D,X :\ else increment hi byte BCC LD3C2 :\ and if carry clear D3C2 .LD3B7 LDA &032C,X :\ esle A=32C,X BNE LD3BF :\ and if not 0 D3BF DEC &032D,X :\ decrement hi byte .LD3BF DEC &032C,X :\ decrement lo byte .LD3C2 TXA :\ A=X EOR #&02 :\ invert bit 2 TAX :\ X=A INC &032C,X :\ Increment 32C/D BNE LD3CE :\ INC &032D,X :\ .LD3CE LDX &DC :\ X=&DC .LD3D0 JMP LD2E3 :\ jump to D2E3 \**********move display point up a line ********************************** .LD3D3 SEC :\ SET CARRY LDA &D6 :\ subtract number of bytes/line from address of SBC &0352 :\ top line of current graphics cell STA &D6 :\ LDA &D7 :\ SBC &0353 :\ CMP &034E :\ compare with bottom of screen memory BCS LD3E8 :\ if outside screen RAM ADC &0354 :\ add screen memory size to wrap it around .LD3E8 STA &D7 :\ store in current address of graphics cell top line LDY #&07 :\ Y=7 RTS :\ and RETURN .LD3ED LDA &0362 :\ get current left colour mask STA &D1 :\ store it LDA &D6 :\ get current top line of graphics cell ADC #&07 :\ ADD 7 STA &D6 :\ BCC LD3FC :\ INC &D7 :\ .LD3FC RTS :\ and return .LD3FD LDA &0363 :\ get right colour mask STA &D1 :\ store it LDA &D6 :\ A=top line graphics cell low BNE LD408 :\ if not 0 D408 DEC &D7 :\ else decrement hi byte .LD408 SBC #&08 :\ subtract 9 (8 + carry) STA &D6 :\ and store in low byte RTS :\ return \******** coordinate subtraction *************************************** .LD40D LDY #&28 :\ X=&28 LDX #&20 :\ Y=&20 .LD411 JSR LD418 :\ INX :\ X=X+2 INX :\ INY :\ Y=Y+2 INY :\ .LD418 SEC :\ set carry LDA &0304,X :\ subtract coordinates SBC &0300,X :\ STA &0300,Y :\ LDA &0305,X :\ SBC &0301,X :\ STA &0301,Y :\ RTS :\ and return .LD42C LDA &DE :\ A=&DE BNE LD437 :\ if A=0 D437 LDX #&28 :\ X=&28 LDY #&2A :\ Y=&2A JSR LCDDE :\ exchange 300/1+Y with 300/1+X .LD437 \ :\ IN THIS CASE THE X AND Y SPANS! LDX #&28 :\ X=&28 LDY #&37 :\ Y=&37 JSR LD48A :\ copy &300/4+Y to &300/4+X \ :\ transferring X and Y spans in this case SEC :\ set carry LDX &DE :\ X=&DE LDA &0330 :\ subtract 32C/D,X from 330/1 SBC &032C,X :\ TAY :\ partial answer in Y LDA &0331 :\ SBC &032D,X :\ BMI LD453 :\ if -ve D453 JSR LD49B :\ else negate Y/A .LD453 STA &DD :\ store A STY &DC :\ and Y LDX #&35 :\ X=&35 .LD459 JSR LD467 :\ get coordinates LSR A :\ STA &0301,X :\ TYA :\ ROR A :\ STA &0300,X :\ DEX :\ DEX :\ .LD467 LDY &0304,X :\ LDA &0305,X :\ BPL LD47B :\ if A is +ve RETURN JSR LD49B :\ else negate Y/A STA &0305,X :\ store back again PHA :\ TYA :\ STA &0304,X :\ PLA :\ get back A .LD47B RTS :\ and exit .LD47C LDA #&08 :\ A=8 BNE LD48C :\ copy 8 bytes .LD480 LDY #&30 :\ Y=&30 .LD482 LDA #&02 :\ A=2 BNE LD48C :\ copy 2 bytes .LD486 LDY #&28 :\ copy 4 bytes from 324/7 to 328/B .LD488 LDX #&24 :\ .LD48A LDA #&04 :\ \***********copy A bytes from 300,X to 300,Y *************************** .LD48C STA &DA :\ .LD48E LDA &0300,X :\ STA &0300,Y :\ INX :\ INY :\ DEC &DA :\ BNE LD48E :\ RTS :\ and return \************* negation routine ****************************************** .LD49B PHA :\ save A TYA :\ A=Y EOR #&FF :\ invert TAY :\ Y=A PLA :\ get back A EOR #&FF :\ invert INY :\ Y=Y+1 BNE LD4A9 :\ if not 0 exit CLC :\ else ADC #&01 :\ add 1 to A .LD4A9 RTS :\ return .LD4AA :\ JSR LD85D :\ check window boundaries and set up screen pointer BNE LD4B7 :\ if A<>0 D4B7 LDA (&D6),Y :\ else get byte from current graphics cell EOR &035A :\ compare with current background colour STA &DA :\ store it RTS :\ and RETURN .LD4B7 PLA :\ get back return link PLA :\ .LD4B9 INC &0326 :\ increment current graphics cursor vertical lo JMP LD545 :\ \OS SERIES IV \GEOFF COX \************************************************************************* \* * \* LATERAL FILL ROUTINE * \* * \************************************************************************* .LD4BF JSR LD4AA :\ check current screen state AND &D1 :\ if A and &D1 <> 0 a plotted point has been found BNE LD4B9 :\ so D4B9 LDX #&00 :\ X=0 JSR LD592 :\ update pointers BEQ LD4FA :\ if 0 then D4FA LDY &031A :\ else Y=graphics scan line ASL &D1 :\ BCS LD4D9 :\ if carry set D4D9 JSR LD574 :\ else D574 BCC LD4FA :\ if carry clear D4FA .LD4D9 JSR LD3FD :\ else D3FD to pick up colour multiplier LDA (&D6),Y :\ get graphics cell line EOR &035A :\ EOR with background colour STA &DA :\ and store BNE LD4F7 :\ if not 0 D4F7 SEC :\ else set carry TXA :\ A=X ADC &0361 :\ add pixels/byte BCC LD4F0 :\ and if carry clear D4F0 INC &DB :\ else increment &DB BPL LD4F7 :\ and if +ve D4F7 .LD4F0 TAX :\ else X=A JSR LD104 :\ display a pixel SEC :\ set carry BCS LD4D9 :\ goto D4D9 .LD4F7 JSR LD574 :\ .LD4FA LDY #&00 :\ Y=0 JSR LD5AC :\ LDY #&20 :\ LDX #&24 :\ JSR LCDE6 :\ exchange 300/3 +Y with 300/3+X .LD506 JSR LD4AA :\ check screen pixel LDX #&04 :\ Y=5 JSR LD592 :\ TXA :\ A=x BNE LD513 :\ if A<>0 d513 DEC &DB :\ else &DB=&dB-1 .LD513 DEX :\ X=X-1 .LD514 JSR LD54B :\ BCC LD540 :\ .LD519 JSR LD3ED :\ update pointers LDA (&D6),Y :\ get byte from graphics line EOR &035A :\ EOR with background colour STA &DA :\ and store it LDA &DC :\ BNE LD514 :\ If A-0 back to D514 LDA &DA :\ else A=&DA BNE LD53D :\ if A<>d53D SEC :\ else set carry TXA :\ A=x ADC &0361 :\ Add number of pixels/byte BCC LD536 :\ and if carry clear D536 INC &DB :\ else inc DB BPL LD53D :\ and if +ve D53D .LD536 TAX :\ get back X JSR LD104 :\ display a point SEC :\ set carry BCS LD519 :\ goto D519 .LD53D JSR LD54B :\ .LD540 LDY #&04 :\ JSR LD5AC :\ .LD545 JSR LD0D9 :\ JMP LD1B8 :\ scale pointers .LD54B LDA &D1 :\ get byte mask PHA :\ save it CLC :\ clear carry BCC LD560 :\ .LD551 PLA :\ get back A INX :\ X=X+1 BNE LD559 :\ if not 0 D559 INC &DB :\ else inc &DB BPL LD56F :\ if +ve D56F .LD559 LSR &D1 :\ BCS LD56F :\ if Bit 7 D1 set D56F ORA &D1 :\ else or withA PHA :\ save result .LD560 LDA &D1 :\ A=&D1 BIT &DA :\ test bits 6 and 7 of &DA PHP :\ save flags PLA :\ get into A EOR &DC :\ EOR and DC PHA :\ save A PLP :\ BEQ LD551 :\ PLA :\ A=A EOR &D1 (byte mask) EOR &D1 :\ .LD56F STA &D1 :\ store it JMP LD0F0 :\ and display a pixel .LD574 LDA #&00 :\ A=0 CLC :\ Clear carry BCC LD583 :\ goto D583 if carry clear .LD579 INX :\ X=X+1 BNE LD580 :\ If <>0 D580 INC &DB :\ else inc &DB BPL LD56F :\ and if +ve d56F .LD580 ASL A :\ A=A*2 BCS LD58E :\ if C set D58E .LD583 ORA &D1 :\ else A=A OR (&D1) BIT &DA :\ set V and M from &DA b6 b7 BEQ LD579 :\ EOR &D1 :\ A=AEOR &D1 LSR A :\ /2 BCC LD56F :\ if carry clear D56F .LD58E ROR A :\ *2 SEC :\ set carry BCS LD56F :\ to D56F .LD592 LDA &0300,X :\ Y/A=(&300/1 +X)-(&320/1) SEC :\ SBC &0320 :\ TAY :\ LDA &0301,X :\ SBC &0321 :\ BMI LD5A5 :\ if result -ve D5A5 JSR LD49B :\ or negate Y/A .LD5A5 STA &DB :\ store A TYA :\ A=Y TAX :\ X=A ORA &DB :\ RTS :\ exit .LD5AC STY &DA :\ Y=&DA TXA :\ A=X TAY :\ Y=A LDA &DB :\ A=&DB BMI LD5B6 :\ if -ve D5B6 LDA #&00 :\ A=0 .LD5B6 LDX &DA :\ X=&DA BNE LD5BD :\ if <>0 D5BD JSR LD49B :\ negate .LD5BD PHA :\ CLC :\ TYA :\ ADC &0300,X :\ Y/A+(&300/1 +X)=(&320/1) STA &0320 :\ PLA :\ ADC &0301,X :\ STA &0321 :\ RTS :\ return \************************************************************************* \* * \* OSWORD 13 - READ LAST TWO GRAPHIC CURSOR POSITIONS * \* * \************************************************************************* .LD5CE \; LDA #&03 :\ A=3 JSR LD5D5 :\ LDA #&07 :\ A=7 .LD5D5 PHA :\ Save A JSR LCDE2 :\ exchange last 2 graphics cursor coordinates with \;current coordinates JSR LD1B8 :\ convert to external coordinates LDX #&03 :\ X=3 PLA :\ save A TAY :\ Y=A .LD5E0 LDA &0310,X :\ get graphics coordinate STA (&F0),Y :\ store it in OS buffer DEY :\ decrement Y and X DEX :\ BPL LD5E0 :\ if +ve do it again RTS :\ then Exit \************************************************************************* \* * \* PLOT Fill triangle routine * \* * \************************************************************************* .LD5EA LDX #&20 :\ X=&20 LDY #&3E :\ Y=&3E JSR LD47C :\ copy 300/7+X to 300/7+Y \;this gets XY data parameters and current graphics \;cursor position JSR LD632 :\ exchange 320/3 with 324/7 if 316/7=<322/3 LDX #&14 :\ X=&14 LDY #&24 :\ Y=&24 JSR LD636 :\ JSR LD632 :\ LDX #&20 :\ LDY #&2A :\ JSR LD411 :\ calculate 032A/B-(324/5-320/1) LDA &032B :\ and store STA &0332 :\ result LDX #&28 :\ set pointers JSR LD459 :\ LDY #&2E :\ JSR LD0DE :\ copy 320/3 32/31 JSR LCDE2 :\ exchange 314/7 with 324/7 CLC :\ JSR LD658 :\ execute fill routine JSR LCDE2 :\ LDX #&20 :\ JSR LCDE4 :\ SEC :\ JSR LD658 :\ LDX #&3E :\ ;X=&3E LDY #&20 :\ ;Y=&20 JSR LD47C :\ ;copy 300/7+X to 300/7+Y JMP LD0D9 :\ ;this gets XY data parameters and current graphics .LD632 \ ;cursor position LDX #&20 :\ X=&20 LDY #&14 :\ Y=&14 .LD636 LDA &0302,X :\ CMP &0302,Y :\ LDA &0303,X :\ SBC &0303,Y :\ BMI LD657 :\ if 302/3+Y>302/3+X return JMP LCDE6 :\ else swap 302/3+X with 302/3+Y \************************************************************************* \* * \* OSBYTE 134 - READ CURSOR POSITION * \* * \************************************************************************* LDA &0318 :\ read current text cursor (X) SEC :\ set carry SBC &0308 :\ subtract left hand column of current text window TAX :\ X=A LDA &0319 :\ get current text cursor (Y) SEC :\ SBC &030B :\ suptract top row of current window TAY :\ Y=A .LD657 RTS :\ and exit .LD658 \;PLOT routines continue \;many of the following routines are just manipulations \;only points of interest will be explained PHP :\ store flags LDX #&20 :\ X=&20 LDY #&35 :\ Y=&35 JSR LD411 :\ 335/6=(324/5+X-320/1) LDA &0336 :\ STA &033D :\ LDX #&33 :\ JSR LD459 :\ set pointers LDY #&39 :\ set 339/C=320/3 JSR LD0DE :\ SEC :\ LDA &0322 :\ SBC &0326 :\ STA &031B :\ LDA &0323 :\ SBC &0327 :\ STA &031C :\ ORA &031B :\ check VDU queque BEQ LD69F :\ .LD688 JSR LD6A2 :\ display a line LDX #&33 :\ JSR LD774 :\ update pointers LDX #&28 :\ JSR LD774 :\ and again! INC &031B :\ update VDU queque BNE LD688 :\ and if not empty do it again INC &031C :\ else increment next byte BNE LD688 :\ and do it again .LD69F PLP :\ pull flags BCC LD657 :\ if carry clear exit .LD6A2 LDX #&39 :\ LDY #&2E :\ .LD6A6 STX &DE :\ LDA &0300,X :\ is 300/1+x<300/1+Y CMP &0300,Y :\ LDA &0301,X :\ SBC &0301,Y :\ BMI LD6BC :\ if so D6BC TYA :\ else A=Y LDY &DE :\ Y=&DE TAX :\ X=A STX &DE :\ &DE=X .LD6BC STY &DF :\ &DF=Y LDA &0300,Y :\ PHA :\ LDA &0301,Y :\ PHA :\ LDX &DF :\ JSR LD10F :\ check for window violations BEQ LD6DA :\ CMP #&02 :\ BNE LD70E :\ LDX #&04 :\ LDY &DF :\ JSR LD482 :\ LDX &DF :\ .LD6DA JSR LD864 :\ set a screen address LDX &DE :\ X=&DE JSR LD10F :\ check for window violations LSR A :\ A=A/2 BNE LD70E :\ if A<>0 then exit BCC LD6E9 :\ else if C clear D6E9 LDX #&00 :\ .LD6E9 LDY &DF :\ SEC :\ LDA &0300,Y :\ SBC &0300,X :\ STA &DC :\ LDA &0301,Y :\ SBC &0301,X :\ STA &DD :\ LDA #&00 :\ .LD6FE ASL A :\ ORA &D1 :\ LDY &DC :\ BNE LD719 :\ DEC &DD :\ BPL LD719 :\ STA &D1 :\ JSR LD0F0 :\ display a point .LD70E LDX &DF :\ restore X PLA :\ and A STA &0301,X :\ store it PLA :\ get back A STA &0300,X :\ and store it RTS :\ exit .LD719 :\ DEC &DC :\ TAX :\ BPL LD6FE :\ STA &D1 :\ JSR LD0F0 :\ display a point LDX &DC :\ INX :\ BNE LD72A :\ INC &DD :\ .LD72A TXA :\ PHA :\ LSR &DD :\ ROR A :\ LDY &0361 :\ number of pixels/byte CPY #&03 :\ if 3 mode = goto D73B BEQ LD73B :\ BCC LD73E :\ else if <3 mode 2 goto D73E LSR &DD :\ else rotate bottom bit of &DD ROR A :\ into Accumulator .LD73B LSR &DD :\ rotate bottom bit of &DD LSR A :\ into Accumulator .LD73E LDY &031A :\ Y=line in current graphics cell containing current :\ point TAX :\ X=A BEQ LD753 :\ .LD744 TYA :\ Y=Y-8 SEC :\ SBC #&08 :\ TAY :\ BCS LD74D :\ DEC &D7 :\ decrement byte of top line off current graphics cell .LD74D JSR LD104 :\ display a point DEX :\ BNE LD744 :\ .LD753 PLA :\ AND &0361 :\ pixels/byte BEQ LD70E :\ TAX :\ LDA #&00 :\ A=0 .LD75C ASL A :\ ORA &0363 :\ or with right colour mask DEX :\ BNE LD75C :\ STA &D1 :\ store as byte mask TYA :\ Y=Y-8 SEC :\ SBC #&08 :\ TAY :\ BCS LD76E :\ if carry clear DEC &D7 :\ decrement byte of top line off current graphics cell .LD76E JSR LD0F3 :\ display a point JMP LD70E :\ and exit via D70E .LD774 INC &0308,X :\ BNE LD77C :\ INC &0309,X :\ .LD77C SEC :\ LDA &0300,X :\ SBC &0302,X :\ STA &0300,X :\ LDA &0301,X :\ SBC &0303,X :\ STA &0301,X :\ BPL LD7C1 :\ .LD791 LDA &030A,X :\ BMI LD7A1 :\ INC &0306,X :\ BNE LD7AC :\ INC &0307,X :\ JMP LD7AC :\ .LD7A1 LDA &0306,X :\ BNE LD7A9 :\ DEC &0307,X :\ .LD7A9 DEC &0306,X :\ .LD7AC CLC :\ LDA &0300,X :\ ADC &0304,X :\ STA &0300,X :\ LDA &0301,X :\ ADC &0305,X :\ STA &0301,X :\ BMI LD791 :\ .LD7C1 RTS :\ \************************************************************************* \* * \* OSBYTE 135 - READ CHARACTER AT TEXT CURSOR POSITION * \* * \************************************************************************* .LD7C2 LDY &0360 :\ get number of logical colours BNE LD7DC :\ if Y<>0 mode <>7 so D7DC LDA (&D8),Y :\ get address of top scan line of current text chr LDY #&02 :\ Y=2 .LD7CB CMP LC4B7,Y :\ compare with conversion table BNE LD7D4 :\ if not equal D7d4 LDA LC4B6,Y :\ else get next lower byte from table DEY :\ Y=Y-1 .LD7D4 DEY :\ Y=Y-1 BPL LD7CB :\ and if +ve do it again .LD7D7 LDY &0355 :\ Y=current screen mode TAX :\ return with character in X RTS :\ .LD7DC JSR LD808 :\ set up copy of the pattern bytes at text cursor LDX #&20 :\ X=&20 .LD7E1 TXA :\ A=&20 PHA :\ Save it JSR LD03E :\ get pattern address for code in A PLA :\ get back A TAX :\ and X .LD7E8 LDY #&07 :\ Y=7 .LD7EA LDA &0328,Y :\ get byte in pattern copy CMP (&DE),Y :\ check against pattern source BNE LD7F9 :\ if not the same D7F9 DEY :\ else Y=Y-1 BPL LD7EA :\ and if +ve D7EA TXA :\ A=X CPX #&7F :\ is X=&7F (delete) BNE LD7D7 :\ if not D7D7 .LD7F9 INX :\ else X=X+1 LDA &DE :\ get byte lo address CLC :\ clear carry ADC #&08 :\ add 8 STA &DE :\ store it BNE LD7E8 :\ and go back to check next character if <>0 TXA :\ A=X BNE LD7E1 :\ if <>0 D7E1 BEQ LD7D7 :\ else D7D7 \***************** set up pattern copy *********************************** .LD808 LDY #&07 :\ Y=7 .LD80A STY &DA :\ &DA=Y LDA #&01 :\ A=1 STA &DB :\ &DB=A .LD810 LDA &0362 :\ A=left colour mask STA &DC :\ store an &DC LDA (&D8),Y :\ get a byte from current text character EOR &0358 :\ EOR with text background colour CLC :\ clear carry .LD81B BIT &DC :\ and check bits of colour mask BEQ LD820 :\ if result =0 then D820 SEC :\ else set carry .LD820 ROL &DB :\ &DB=&DB+Carry BCS LD82E :\ if carry now set (bit 7 DB originally set) D82E LSR &DC :\ else &DC=&DC/2 BCC LD81B :\ if carry clear D81B TYA :\ A=Y ADC #&07 :\ ADD (7+carry) TAY :\ Y=A BCC LD810 :\ .LD82E LDY &DA :\ read modified values into Y and A LDA &DB :\ STA &0328,Y :\ store copy DEY :\ and do it again BPL LD80A :\ until 8 bytes copied RTS :\ exit \********* pixel reading ************************************************* .LD839 PHA :\ store A TAX :\ X=A JSR LD149 :\ set up positional data PLA :\ get back A TAX :\ X=A JSR LD85F :\ set a screen address after checking for window \ :\ violations BNE LD85A :\ if A<>0 D85A to exit with A=&FF LDA (&D6),Y :\ else get top line of current graphics cell .LD847 ASL A :\ A=A*2 C=bit 7 ROL &DA :\ &DA=&DA+2 +C C=bit 7 &DA ASL &D1 :\ byte mask=bM*2 +carry from &DA PHP :\ save flags BCS LD851 :\ if carry set D851 LSR &DA :\ else restore &DA with bit '=0 .LD851 PLP :\ pull flags BNE LD847 :\ if Z set D847 LDA &DA :\ else A=&DA AND number of colours in current mode -1 AND &0360 :\ RTS :\ then exit .LD85A LDA #&FF :\ A=&FF .LD85C RTS :\ exit \********** check for window violations and set up screen address ********** .LD85D LDX #&20 :\ X=&20 .LD85F JSR LD10F :\ BNE LD85C :\ if A<>0 there is a window violation so D85C .LD864 LDA &0302,X :\ else set up graphics scan line variable EOR #&FF :\ TAY :\ AND #&07 :\ STA &031A :\ in 31A TYA :\ A=Y LSR A :\ A=A/2 LSR A :\ A=A/2 LSR A :\ A=A/2 ASL A :\ A=A*2 this gives integer value bit 0 =0 TAY :\ Y=A LDA (&E0),Y :\ get high byte of offset from screen RAM start STA &DA :\ store it INY :\ Y=Y+1 LDA (&E0),Y :\ get lo byte LDY &0356 :\ get screen map type BEQ LD884 :\ if 0 (modes 0,1,2) goto D884 LSR &DA :\ else &DA=&DA/2 ROR A :\ and A=A/2 +C if set .LD884 \ :\ so 2 byte offset =offset/2 ADC &0350 :\ add screen top left hand corner lo STA &D6 :\ store it LDA &DA :\ get high byte ADC &0351 :\ add top left hi STA &D7 :\ store it LDA &0301,X :\ STA &DA :\ LDA &0300,X :\ PHA :\ AND &0361 :\ and then Add pixels per byte-1 ADC &0361 :\ TAY :\ Y=A LDA LC406,Y :\ A=&80 /2^Y using look up table STA &D1 :\ store it PLA :\ get back A LDY &0361 :\ Y=&number of pixels/byte CPY #&03 :\ is Y=3 (modes 1,6) BEQ LD8B2 :\ goto D8B2 BCS LD8B5 :\ if mode =1 or 4 D8B5 ASL A :\ A/&DA =A/&DA *2 ROL &DA :\ .LD8B2 ASL A :\ ROL &DA :\ .LD8B5 AND #&F8 :\ clear bits 0-2 CLC :\ clear carry ADC &D6 :\ add A/&DA to &D6/7 STA &D6 :\ LDA &DA :\ ADC &D7 :\ BPL LD8C6 :\ if result +ve D8C6 SEC :\ else set carry SBC &0354 :\ and subtract screen memory size making it wrap round .LD8C6 STA &D7 :\ store it in &D7 LDY &031A :\ get line in graphics cell containing current graphics .LD8CB LDA #&00 :\ point A=0 RTS :\ And exit .LD8CE :\ PHA :\ Push A LDA #&A0 :\ A=&A0 LDX &026A :\ X=number of items in VDU queque BNE LD916 :\ if not 0 D916 BIT &D0 :\ else check VDU status byte BNE LD916 :\ if either VDU is disabled or plot to graphics :\ cursor enabled then D916 BVS LD8F5 :\ if cursor editing enabled D8F5 LDA &035F :\ else get 6845 register start setting AND #&9F :\ clear bits 5 and 6 ORA #&40 :\ set bit 6 to modify last cursor size setting JSR LC954 :\ change write cursor format LDX #&18 :\ X=&18 LDY #&64 :\ Y=&64 JSR LD482 :\ set text input cursor from text output cursor JSR LCD7A :\ modify character at cursor poistion LDA #&02 :\ A=2 JSR LC59D :\ bit 1 of VDU status is set to bar scrolling .LD8F5 LDA #&BF :\ A=&BF JSR LC5A8 :\ bit 6 of VDU status =0 PLA :\ Pull A AND #&7F :\ clear hi bit (7) JSR LC4C0 :\ entire VDU routine !! LDA #&40 :\ A=&40 JMP LC59D :\ exit .LD905 LDA #&20 :\ A=&20 BIT &D0 :\ if bit 6 cursor editing is set BVC LD8CB :\ BNE LD8CB :\ or bit 5 is set exit &D8CB JSR LD7C2 :\ read a character from the screen BEQ LD917 :\ if A=0 on return exit via D917 PHA :\ else store A JSR LC664 :\ perform cursor right .LD916 PLA :\ restore A .LD917 RTS :\ and exit .LD918 :\ LDA #&BD :\ zero bits 2 and 6 of VDU status JSR LC5A8 :\ JSR LC951 :\ set normal cursor LDA #&0D :\ A=&0D RTS :\ and return \ :\ this is response of CR as end of edit line \************************************************************************* \* * \* OSBYTE 132 - READ BOTTOM OF DISPLAY RAM * \* * \************************************************************************* .LD923 LDX &0355 :\ Get current screen mode \************************************************************************* \* * \* OSBYTE 133 - READ LOWEST ADDRESS FOR GIVEN MODE * \* * \************************************************************************* .LD926 TXA :\ A=X AND #&07 :\ Ensure mode 0-7 TAY :\ Pass to Y into index into screen size table LDX LC440,Y :\ X=screen size type, 0-4 LDA LC45E,X :\ A=high byte of start address for screen type LDX #&00 :\ Returned address is &xx00 BIT &028E :\ Check available RAM BMI LD93E :\ If bit 7 set then 32K RAM, so return address AND #&3F :\ 16K RAM, so drop address to bottom 16K CPY #&04 :\ Check screen mode BCS LD93E :\ If mode 4-7, return the address TXA :\ If mode 0-3, return &0000 as not enough memory .LD93E \ exit TAY :\ Pass high byte of address to Y .LD93F RTS :\ and return address in YX \************************************************************************* \************************************************************************* \** ** \** SYSTEM STARTUP ** \** ** \************************************************************************* \************************************************************************* \* DEFAULT PAGE &02 SETTINGS (VECTORS, OSBYTE VARIABLES) \* RESET CODE \************************************************************************* \* * \* DEFAULT SYSTEM SETTINGS FOR PAGE &02 * \* * \************************************************************************* \------------------------------------------------------------------------- \| | \| DEFAULT VECTOR TABLE | \| | \------------------------------------------------------------------------- BPL LD925 :\ USERV &200 EQUB &54 :\ BRKV &202 EQUB &DC :\ IRQ1V &204 EQUB &93 :\ EQUB &DC :\ IRQ2V &206 BIT #&DE :\ BIT #&DF :\ CLIV &208 ADC (&E7) :\ BYTEV &20A EQUB &EB :\ WORDV &20C EQUB &E7 :\ WRCHV &20E LDY &E0 :\ CMP &DE :\ RDCHV &210 ADC &8EF2,X :\ FILEV &212 :\ ARGSV &214 SBC (&C9),Y :\ BGETV &216 EQUB &F4 :\ BPUTV &218 AND #&F5 :\ LDX &FF :\ GBPBV &21A DEX :\ FINDV &21C EQUB &F3 :\ FSCV &21E LDA (&F1),Y :\ LDX &FF :\ EVNTV &220 LDX &FF :\ UPTV &222 LDX &FF :\ NETV &224 LDX &FF :\ VDUV &226 EQUB &02 :\ KEYV &228 EQUB &EF :\ INSBV &22A EQUB &B3 :\ CPX &64 :\ REMVB &22C CPX &D1 :\ CNPV &22E SBC (&A6,X) :\ IND1V &230 EQUB &FF :\ IND2V &232 LDX &FF :\ LDX &FF :\ IND3V &234 \------------------------------------------------------------------------- \| | \| DEFAULT MOS VARIABLES SETTINGS | \| | \------------------------------------------------------------------------- \* Read/Written by OSBYTE &A6 to &FC BCC LD979 :\ OSBYTE variables base address &236 *FX166/7 \ :\ (address to add to osbyte number) EQUB &9F :\ Address of extended vectors &238 *FX168/9 .LD979 \ Address of ROM information table &23A *FX170/1 ORA &02A1 :\ EQUB &2B :\ Address of key translation table &23C *FX172/3 BEQ LD97F :\ Address of VDU variables &23E *FX174/5 .LD97F EQUB &03 :\ CFS/Vertical sync Timeout counter &240 *FX176 BRK :\ BRK :\ Current input buffer number &241 *FX177 EQUB &FF :\ Keyboard interrupt processing flag &242 *FX178 BRK :\ Primary OSHWM (default PAGE) &243 *FX179 BRK :\ Current OSHWM (PAGE) &244 *FX180 ORA (&00,X) :\ RS423 input mode &245 *FX181 :\ Character explosion state &246 *FX182 BRK :\ CFS/RFS selection, CFS=0 ROM=2 &247 *FX183 BRK :\ Video ULA control register copy &248 *FX184 BRK :\ Pallette setting copy &249 *FX185 BRK :\ ROM number selected at last BRK &24A *FX186 EQUB &FF :\ BASIC ROM number &24B *FX187 TSB &04 :\ Current ADC channel number &24C *FX188 BRK :\ ADC conversion 0/8bit/12bit &24E *FX190 EQUB &FF :\ RS423 busy flag (bit 7=0, busy) &24F *FX191 LSR &19,X :\ ACIA control register copy &250 *FX192 ORA &3219,Y :\ Flash mark period count &252 *FX194 PHP :\ Keyboard auto-repeat rate &255 *FX197 BRK :\ *EXEC file handle &256 *FX198 BRK :\ *SPOOL file handle &257 *FX199 BRK :\ Break/Escape handing &258 *FX200 BRK :\ Econet keyboard disable flag &259 *FX201 JSR &0009 :\ Keyboard status &25A *FX202 \ :\ bit 3=1 shift pressed \ :\ bit 4=0 caps lock \ :\ bit 5=0 shift lock \ :\ bit 6=1 control bit \ :\ bit 7=1 shift enabled BRK :\ Cassette/RS423 flag (0=CFS, &40=RS423) &25D *FX205 BRK :\ Econet OSBYTE/OSWORD interception flag &25E *FX206 BRK :\ Econet OSRDCH interception flag &25F *FX207 BRK :\ Econet OSWRCH interception flag &260 *FX208 BVC LD9A3 :\ Speech enable/disable flag (&20/&50) &261 *FX209 .LD9A3 EQUB &03 :\ BELL channel number &263 *FX211 BCC LDA0A :\ BELL amplitude/Envelope number &264 *FX212 ASL &81 :\ BELL duration &266 *FX214 BRK :\ Length of current soft key string &268 *FX216 BRK :\ Lines printed since last paged halt &269 *FX217 BRK :\ 0-(Number of items in VDU queue) &26A *FX218 ORA #&1B :\ TAB key value &26B *FX219 \ :\ The following are input buffer code interpretation variables for \ :\ bytes entered into the input buffer with b7 set (is 128-255). \ :\ The standard keyboard only enters characters &80-&BF with the \ :\ function keys, but other characters can be entered, for instance \ :\ via serial input of via other keyboard input systems. \ :\ 0=ignore key \ :\ 1=expand as soft key \ :\ 2-FF add to base for ASCII code ORA (&D0,X) :\ C0-&CF &26D *FX221 CPX #&F0 :\ E0-&EF &26F *FX223 ORA (&80,X) :\ 80-&8F function key &271 *FX225 BCC LD9B5 :\ A0-&AF Ctrl+function key &273 *FX227 .LD9B5 BRK :\ ESCAPE key status (0=ESC, 1=ASCII) &275 *FX229 BRK :\ ESCAPE action &276 *FX230 .LD9B7 EQUB &FF :\ USER 6522 Bit IRQ mask &277 *FX231 EQUB &FF :\ 6850 ACIA Bit IRQ bit mask &278 *FX232 EQUB &FF :\ System 6522 IRQ bit mask &279 *FX233 BRK :\ Tube prescence flag &27A *FX234 BRK :\ Speech processor prescence flag &27B *FX235 BRK :\ Character destination status &27C *FX236 BRK :\ Cursor editing status &27D *FX237 \****************** Soft Reset high water mark *************************** BRK :\ unused &27E *FX238 BRK :\ unused &27F *FX239 BRK :\ Country code &280 *FX240 BRK :\ User flag &281 *FX241 STZ &05 :\ Serial ULA control register copy &282 *FX242 EQUB &FF :\ Soft key consitancy flag &284 *FX244 ORA (&0A,X) :\ Printer destination &285 *FX245 \****************** Hard Reset High water mark *************************** BRK :\ Break Intercept Vector JMP opcode &288 *FX247 BRK :\ Break Intercept Vector address low &288 *FX248 BRK :\ Break Intercept Vector address high &289 *FX249 BRK :\ unused (memory used for VDU) &28A *FX250 BRK :\ unused (memory used for display) &28B *FX251 EQUB &FF :\ Current language ROM number &28C *FX252 .LD9CD \****************** Power-On Reset High Water mark *********************** \************************************************************************** \************************************************************************** \** ** \** RESET (BREAK) ENTRY POINT ** \** ** \** Power up Enter with nothing set, 6522 System VIA IER bits ** \** 0 to 6 will be clear ** \** ** \** BREAK IER bits 0 to 6 one or more will be set 6522 IER ** \** not reset by BREAK ** \** ** \************************************************************************** \************************************************************************** LDA #&40 :\ set NMI first instruction to RTI STA &0D00 :\ NMI ram start SEI :\ disable interrupts just in case CLD :\ clear decimal flag LDX #&FF :\ reset stack to where it should be TXS :\ (&1FF) LDA LFE4E :\ read interupt enable register of the system VIA ASL A :\ shift bit 7 into carry PHA :\ save what's left BEQ LD9E7 :\ if Power up A=0 so D9E7 LDA &0258 :\ else if BREAK pressed read BREAK Action flags :\ (set by *FX200,n) LSR A :\ divide by 2 CMP #&01 :\ if (bit 1 not set by *FX200) BNE LDA03 :\ then &DA03 LSR A :\ divide A by 2 again (A=0 if *FX200,2/3 else A=n/4) .LD9E7 \********** clear memory routine ****************************************** LDX #&04 :\ get page to start clearance from (4) STX &01 :\ store it in ZP 01 STA &00 :\ store A at 00 TAY :\ and in Y to set loop counter .LD9EE STA (&00),Y :\ clear store CMP &01 :\ until address &01 =0 BEQ LD9FD :\ INY :\ increment pointer BNE LD9EE :\ if not zero loop round again INY :\ else increment again (Y=1) this avoids overwriting \;RTI instruction at &D00 INX :\ increment X INC &01 :\ increment &01 BPL LD9EE :\ loop until A=&80 then exit .LD9FD \;note that RAM addressing for 16k loops around so \;&4000=&00 hence checking &01 for 00. This avoids \;overwriting zero page on BREAK STX &028E :\ writes marker for available RAM 40 =16k,80=32 STX &0284 :\ write soft key consistency flag .LDA03 \**+********** set up system VIA ***************************************** LDX #&0F :\ set PORT B to output on bits 0-3 Input 4-7 STX LFE42 :\ .LDA08 \************************************************************************* \* * \* set addressable latch IC 32 for peripherals via PORT B * \* * \* :\ bit 3 set sets addressed latch high adds 8 to VIA address * \* :\ bit 3 reset sets addressed latch low * \* * \* Peripheral VIA bit 3=0 VIA bit 3=1 * \* * \* Sound chip Enabled Disabled * \* speech chip (RS) Low High * \* speech chip (WS) Low High * \* Keyboard Auto Scan Disabled Enabled * \* C0 address modifier Low High * \* C1 address modifier Low High * \* Caps lock LED ON OFF * \* Shift lock LED ON OFF * \* * \* C0 & C1 are involved with hardware scroll screen address * \************************************************************************* \ :\ X=&F on entry DEX :\ loop start STX LFE40 :\ write latch IC32 CPX #&09 :\ is it 9 BCS LDA08 :\ if so go back and do it again \;X=8 at this point \;Caps lock On, SHIFT lock undetermined \;Keyboard Autoscan on \;sound disabled (may still sound) INX :\ X=9 .LDA11 TXA :\ A=X JSR LF02A :\ interrogate keyboard CPX #&80 :\ for keyboard links 9-2 and CTRL key (1) ROR &FC :\ rotate MSB into bit 7 of &FC TAX :\ get back value of X for loop DEX :\ decrement it BNE LDA11 :\ and if >0 do loop again \; on exit if Carry set link 3 made \;link 2 = bit 0 of &FC and so on \;if CTRL pressed bit 7 of &FC=1 \;X=0 STX &028D :\ clear last BREAK flag ROL &FC :\ CTRL is now in carry &FC is keyboard links JSR LEEEB :\ set LEDs carry on entry bit 7 of A on exit ROR A :\ get carry back into carry flag \****** set up page 2 **************************************************** LDX #&9C :\ LDY #&8D :\ PLA :\ get back A from &D9DB BEQ LDA36 :\ if A=0 power up reset so DA36 with X=&9C Y=&8D LDY #&7E :\ else Y=&7E BCC LDA42 :\ and if not CTRL-BREAK DA42 WARM RESET LDY #&87 :\ else Y=&87 COLD RESET INC &028D :\ &28D=1 .LDA36 INC &028D :\ &28D=&28D+1 LDA &FC :\ get keyboard links set EOR #&FF :\ invert STA &028F :\ and store at &28F LDX #&90 :\ X=&90 .LDA42 \********** set up page 2 ************************************************* \ :\ on entry &28D=0 Warm reset, X=&9C, Y=&7E \ :\ &28D=1 Power up , X=&90, Y=&8D \ :\ &28D=2 Cold reset, X=&9C, Y=&87 LDA #&00 :\ A=0 .LDA44 CPX #&CE :\ zero &200+X to &2CD BCC LDA4A :\ LDA #&FF :\ then set &2CE to &2FF to &FF .LDA4A STA &0200,X :\ INX :\ BNE LDA44 :\ \ :\ A=&FF X=0 STA LFE63 :\ set port A of user via to all outputs (printer out) TXA :\ A=0 LDX #&E2 :\ X=&E2 .LDA56 STA &00,X :\ zero zeropage &E2 to &FF INX :\ BNE LDA56 :\ X=0 .LDA5B LDA LD93F,Y :\ copy data from &D93F+Y STA &01FF,Y :\ to &1FF+Y DEY :\ until BNE LDA5B :\ 1FF+Y=&200 LDA #&62 :\ A=&62 STA &ED :\ store in &ED JSR LFB0A :\ set up ACIA \;X=0 \************** clear interrupt and enable registers of Both VIAs ******** LDA #&7F :\ INX :\ .LDA6E STA LFE4D,X :\ STA LFE6D,X :\ DEX :\ BPL LDA6E :\ CLI :\ briefly allow interrupts to clear anything pending SEI :\ disallow again NEXTBGET All VIA IRQs are disabled BIT &FC :\ if bit 6=1 then JSR &F055 (normally 0) BVC LDA80 :\ else DA80 JSR LF055 :\ F055 JMP (&FDFE) probably causes a BRK unless .LDA80 \;hardware there redirects it. \; LDX #&F2 :\ enable interrupts 1,4,5,6 of system VIA STX LFE4E :\ \;0 Keyboard enabled as needed \;1 Frame sync pulse \;4 End of A/D conversion \;5 T2 counter (for speech) \;6 T1 counter (10 mSec intervals) \; LDX #&04 :\ set system VIA PCR STX LFE4C :\ \;CA1 to interrupt on negative edge (Frame sync) \;CA2 Handshake output for Keyboard \;CB1 interrupt on negative edge (end of conversion) \;CB2 Negative edge (Light pen strobe) \; LDA #&60 :\ set system VIA ACR STA LFE4B :\ \;disable latching \;disable shift register \;T1 counter continuous interrupts \;T2 counter timed interrupt LDA #&0E :\ set system VIA T1 counter (Low) STA LFE46 :\ \;this becomes effective when T1 hi set STA LFE6C :\ set user VIA PCR \;CA1 interrupt on -ve edge (Printer Acknowledge) \;CA2 High output (printer strobe) \;CB1 Interrupt on -ve edge (user port) \;CB2 Negative edge (user port) STA LFEC0 :\ set up A/D converter \;Bits 0 & 1 determine channel selected \;Bit 3=0 8 bit conversion bit 3=1 12 bit CMP LFE6C :\ read user VIA IER if = &0E then DAA2 chip present BEQ LDAA2 :\ so goto DAA2 INC &0277 :\ else increment user VIA mask to 0 to bar all .LDAA2 \;user VIA interrupts LDA #&27 :\ set T1 (hi) to &27 this sets T1 to &270E (9998 uS) STA LFE47 :\ or 10msec, interrupts occur every 10msec therefore STA LFE45 :\ JSR LEC60 :\ clear the sound channels LDA &0282 :\ read serial ULA control register AND #&7F :\ zero bit 7 JSR LE6A7 :\ and set up serial ULA LDX &0284 :\ get soft key status flag BEQ LDABD :\ if 0 (keys OK) then DABD JSR LE9C8 :\ else reset function keys .LDABD \************************************************************************* \* * \* Check sideways ROMs and make ROM list * \* * \************************************************************************* :\ X=0 JSR LDC16 :\ set up ROM latch and RAM copy to X LDX #&03 :\ set X to point to offset in table LDY &8007 :\ get copyright offset from ROM .LDAC5 :\ DF0C = ")C(",0 LDA &8000,Y :\ get first byte CMP LDF0C,X :\ compare it with table byte BNE LDAFB :\ if not the same then goto DAFB INY :\ point to next byte DEX :\ (s) BPL LDAC5 :\ and if still +ve go back to check next byte :\ this point is reached if 5 bytes indicate valid :\ ROM (offset +4 in (C) string) \************************************************************************* \* Check first 1K of each ROM against higher priority ROMs to ensure that* \* there are no duplicates, if duplicate found ignore lower priority ROM * \************************************************************************* LDX &F4 :\ get RAM copy of ROM No. in X LDY &F4 :\ and Y .LDAD5 INY :\ increment Y to check CPY #&10 :\ if ROM 15 is current ROM BCS LDAFF :\ if equal or more than 16 goto &DAFF :\ to store catalogue byte TYA :\ else put Y in A EOR #&FF :\ invert it STA &FA :\ and store at &FA LDA #&7F :\ store &7F at STA &FB :\ &FB to get address &7FFF-Y .LDAE3 STY LFE30 :\ set new ROM LDA (&FA),Y :\ Get byte STX LFE30 :\ switch back to previous ROM CMP (&FA),Y :\ and compare with previous byte called BNE LDAD5 :\ if not the same then go back and do it again :\ with next rom up INC &FA :\ else increment &FA to point to new location BNE LDAE3 :\ if &FA<>0 then check next byte INC &FB :\ else inc &FB LDA &FB :\ and check that it doesn't exceed CMP #&84 :\ &84 (1k checked) BCC LDAE3 :\ then check next byte(s) .LDAFB LDX &F4 :\ X=(&F4) BPL LDB0C :\ if +ve then &DB0C .LDAFF LDA &8006 :\ get rom type STA &02A1,X :\ store it in catalogue AND #&8F :\ check for BASIC (bit 7 not set) BNE LDB0C :\ if not BASIC the DB0C STX &024B :\ else store X at BASIC pointer .LDB0C INX :\ increment X to point to next ROM CPX #&10 :\ is it 15 or less BCC LDABD :\ if so goto &DABD for next ROM \OS SERIES V \GEOFF COX \************************************************************************* \* * \* Check SPEECH System * \* * \************************************************************************* :\ X=&10 BIT LFE40 :\ if bit 7 low then we have speech system fitted BMI LDB27 :\ else goto DB27 DEC &027B :\ (027B)=&FF to indicate speech present .LDB19 LDY #&FF :\ Y=&FF JSR LEE7F :\ initialise speech generator DEX :\ via this BNE LDB19 :\ loop :\ X=0 STX LFE48 :\ set T2 timer for speech STX LFE49 :\ .LDB27 \*********** SCREEN SET UP ********************************************** :\ X=0 LDA &028F :\ get back start up options (mode) JSR LC300 :\ then jump to screen initialisation LDY #&CA :\ Y=&CA JSR LE4F1 :\ to enter this in keyboard buffer :\ this enables the *KEY 10 facility \********* enter BREAK intercept with Carry Clear ************************ JSR LEAD9 :\ check to see if BOOT address is set up, if so :\ JMP to it JSR LF140 :\ set up cassette options LDA #&81 :\ test for tube to FIFO buffer 1 STA LFEE0 :\ LDA LFEE0 :\ ROR A :\ put bit 0 into carry BCC LDB4D :\ if no tube then DB4D LDX #&FF :\ else JSR LF168 :\ issue ROM service call &FF :\ to initialise TUBE system BNE LDB4D :\ if not 0 on exit (Tube not initialised) DB4D DEC &027A :\ else set tube flag to show it's active .LDB4D LDY #&0E :\ set current value of PAGE LDX #&01 :\ issue claim absolute workspace call JSR LF168 :\ via F168 LDX #&02 :\ send private workspace claim call JSR LF168 :\ via F168 STY &0243 :\ set primary OSHWM STY &0244 :\ set current OSHWM LDX #&FE :\ issue call for Tube to explode character set etc. LDY &027A :\ Y=FF if tube present else Y=0 JSR LF168 :\ and make call via F168 AND &0267 :\ if A=&FE and bit 7 of 0267 is set then continue BPL LDB87 :\ else ignore start up message LDY #&02 :\ output to screen JSR LDEA9 :\ 'BBC Computer ' message LDA &028D :\ 0=warm reset, anything else continue BEQ LDB82 :\ LDY #&16 :\ by checking length of RAM BIT &028E :\ BMI LDB7F :\ and either LDY #&11 :\ .LDB7F JSR LDEA9 :\ finishing message with '16K' or '32K' .LDB82 LDY #&1B :\ and two newlines JSR LDEA9 :\ .LDB87 \********* enter BREAK INTERCEPT ROUTINE WITH CARRY SET (call 1) SEC :\ JSR LEAD9 :\ look for break intercept jump do *TV etc JSR LE9D9 :\ set up LEDs in accordance with keyboard status PHP :\ save flags PLA :\ and get back in A LSR A :\ zero bits 4-7 and bits 0-2 bit 4 which was bit 7 LSR A :\ may be set LSR A :\ LSR A :\ EOR &028F :\ eor with start-up options which may or may not AND #&08 :\ invert bit 4 TAY :\ Y=A LDX #&03 :\ make fs initialisation call, passing boot option in Y JSR LF168 :\ Eg, RUN, EXEC or LOAD !BOOT file BEQ LDBBE :\ if a ROM accepts this call then DBBE TYA :\ else put Y in A BNE LDBB8 :\ if Y<>0 DBB8 LDA #&8D :\ else set up standard cassete baud rates JSR LF135 :\ via &F135 LDX #&D2 :\ LDY #&EA :\ DEC &0267 :\ decrement ignore start up message flag JSR OS_CLI :\ and execute */!BOOT INC &0267 :\ restore start up message flag BNE LDBBE :\ if not zero then DBBE .LDBB8 LDA #&00 :\ else A=0 TAX :\ X=0 JSR LF137 :\ set tape speed .LDBBE \******** Preserve current language on soft RESET ************************ LDA &028D :\ get last RESET Type BNE LDBC8 :\ if not soft reset DBC8 LDX &028C :\ else get current language ROM address BPL LDBE6 :\ if +ve (language available) then skip search routine .LDBC8 \************************************************************************* \* * \* SEARCH FOR LANGUAGE TO ENTER (Highest priority) * \* * \************************************************************************* LDX #&0F :\ set pointer to highest available rom .LDBCA LDA &02A1,X :\ get rom type from map ROL A :\ put hi-bit into carry, bit 6 into bit 7 BMI LDBE6 :\ if bit 7 set then ROM has a language entry so DBE6 DEX :\ else search for language until X=&ff BPL LDBCA :\ \*************** check if tube present *********************************** LDA #&00 :\ if bit 7 of tube flag is set BMI succeeds BIT &027A :\ and TUBE is connected else BMI LDC08 :\ make error \********* no language error *********************************************** BRK :\ SBC &614C,Y :\ error number ROR &7567 :\ ADC (&67,X) :\ ADC &3F :\ BRK :\ .LDBE6 CLC :\ \************************************************************************* \* * \* OSBYTE 142 - ENTER LANGUAGE ROM AT &8000 * \* * \* X=rom number C set if OSBYTE call clear if initialisation * \* * \************************************************************************* .LDBE7 \save flags PHP :\ STX &028C :\ put X in current ROM page JSR LDC16 :\ select that ROM LDA #&80 :\ A=128 LDY #&08 :\ Y=8 JSR LDEAB :\ display text string held in ROM at &8008,Y STY &FD :\ save Y on exit (end of language string) JSR OSNEWL :\ two line feeds JSR OSNEWL :\ are output PLP :\ then get back flags LDA #&01 :\ A=1 required for language entry BIT &027A :\ check if tube exists BMI LDC08 :\ and goto DC08 if it does JMP &8000 :\ else enter language at &8000 \************************************************************************* \* * \* TUBE FOUND, ENTER TUBE SOFTWARE * \* * \************************************************************************* \ enter tube environment .LDC08 JMP &0400 :\ \************************************************************************* \* * \* OSRDRM entry point * \* * \* get byte from PHROM or page ROM * \* Y= rom number, address is in &F6/7 * \************************************************************************* \ get current ROM number into X LDX &F4 :\ STY &F4 :\ store new number in &F4 STY LFE30 :\ switch in ROM LDY #&00 :\ get current PHROM address LDA (&F6),Y :\ and get byte \******** Set up Sideways ROM latch and RAM copy ************************* \ :\ on entry X=ROM number .LDC16\ RAM copy of rom latch STX &F4 :\ STX LFE30 :\ write to rom latch RTS :\ and return \************************************************************************** \************************************************************************** \** ** \** MAIN IRQ Entry point ** \** ** \** ** \************************************************************************** \************************************************************************** \ON ENTRY STACK contains STATUS REGISTER,PCH,PCL :\ \ save A STA &FC :\ PLA :\ get back status (flags) PHA :\ and save again AND #&10 :\ check if BRK flag set BNE LDC27 :\ if so goto DC27 JMP (&0204) :\ else JMP (IRQ1V) \************************************************************************* \* * \* BRK handling routine * \* * \************************************************************************* \ save X on stack .LDC27 TXA :\ PHA :\ TSX :\ get status pointer LDA &0103,X :\ get Program Counter lo CLD :\ SEC :\ set carry SBC #&01 :\ subtract 2 (1+carry) STA &FD :\ and store it in &FD LDA &0104,X :\ get hi byte SBC #&00 :\ subtract 1 if necessary STA &FE :\ and store in &FE LDA &F4 :\ get currently active ROM STA &024A :\ and store it in &24A STX &F0 :\ store stack pointer in &F0 LDX #&06 :\ and issue ROM service call 6 JSR LF168 :\ (User BRK) to ROMs \ :\ at this point &FD/E point to byte after BRK \ :\ ROMS may use BRK for their own purposes LDX &028C :\ get current language JSR LDC16 :\ and activate it PLA :\ get back original value of X TAX :\ LDA &FC :\ get back original value of A CLI :\ allow interrupts JMP (&0202) :\ and JUMP via BRKV (normally into current language) \************************************************************************* \* * \* DEFAULT BRK HANDLER * \* * \************************************************************************* \ Y=0 to point to byte after BRK LDY #&00 :\ JSR LDEB1 :\ print message LDA &0267 :\ if BIT 0 set and DISC EXEC error ROR A :\ occurs .LDC5D \hang up machine!!!! BCS LDC5D :\ JSR OSNEWL :\ else print two newlines JSR OSNEWL :\ JMP LDBB8 :\ and set tape speed before entering current \ :\ language \ ACIA IRQ, RxRDY but both Serial and Printer buffers empty \ --------------------------------------------------------- \ DC68 SEC .LDC68 SEC :\ ROR &024F :\ Set b7 of RS423 busy flag BIT &0250 :\ check bit 7 of current ACIA control register BPL LDC78 :\ if interrupts NOT enabled DC78 JSR LE741 :\ else E741 to check if serial buffer full LDX #&00 :\ X=&00 to set RTS low BCS LDC7A :\ if carry set goto DC7A to transfer data .LDC78 \ X=&40 to set RTS high LDX #&40 :\ .LDC7A \ Jump to set ACIA control register JMP LE17A :\ \ Serial IRQ and RxRDY - Get byte and store in serial buffer \ ---------------------------------------------------------- \ Read data from ACIA .LDC7D LDY LFE09 :\ AND #&3A :\ Check PE-RO-FE-DCD BNE LDCB8 :\ If any set, jump to generate Serial Error Event \ Serial IRQ and RxRDY, no errors \ ------------------------------- LDX &025C :\ Read RS423 input suppression flag BNE LDC92 :\ If not 0, jump to ignore INX :\ X=1, serial input buffer JSR LE4F3 :\ Put byte in buffer JSR LE741 :\ Check if serial buffer almost full BCC LDC78 :\ If almost full, jump to set RTS high .LDC92 \ Return RTS :\ \************************************************************************* \* * \* Main IRQ Handling routines, default IRQ1V destination * \* * \************************************************************************* \ Clear decimal flag CLD :\ LDA &FC :\ Get original value of A PHA :\ Save it TXA :\ Save X PHA :\ TYA :\ and Y PHA :\ LDA #&DE :\ Stack return address to &DE82 PHA :\ DC9D PHA LDA #&81 :\ DC9E LDA #&81 PHA :\ DCA0 PHA CLV :\ Clear V flag .LDCA2 \ Read ACIA status register LDA LFE08 :\ BVS LDCA9 :\ b6 set, jump with serial parity error BPL LDD06 :\ b7=0, no ACIA interrupt, jump to check VIAs \ ACIA Interrupt or ACIA Parity Error \ ----------------------------------- .LDCA9 \ Get RS423 timeout counter LDX &EA :\ DEX :\ Decrement it BMI LDCDE :\ If 0 or <0, RS423 owns 6850, jump to DCDE BVS LDCDD :\ If &41..&80, nobody owns 6850, jump to exit JMP LF588 :\ CFS owns 6850, jump to read ACIA in CFS routines \ ACIA Data Carrier Detect \ ------------------------ \ Read ACIA data .LDCB3 LDY LFE09 :\ ROL A :\ ASL A :\ Rotate ACIA Status back .LDCB8 \ X=ACIA Status TAX :\ TYA :\ A=ACIA Data LDY #&07 :\ Y=07 for RS423 Error Event JMP LE494 :\ Jump to issue event \ ACIA IRQ, TxRDY - Send a byte \ ----------------------------- \ DCBF \ LDX #&02 .LDCBF LDX #&02 :\ JSR LE460 :\ Read from Serial output buffer BCC LDCD6 :\ Buffer is not empty, jump to send byte LDA &0285 :\ Read printer destination CMP #&02 :\ Is it serial printer?? BNE LDC68 :\ Serial buffer empty, not Serial printer, jump to ... DC68 INX :\ X=3 for Printer buffer JSR LE460 :\ Read from Printer buffer ROR &02D2 :\ Copy Byte Fetched/Not fetched into Printer Buffer full flag BMI LDC68 :\ Printer buffer was empty, so jump to ... DC68 .LDCD6 \ Send byte to ACIA STA LFE09 :\ LDA #&E7 :\ Set timeout counter to &E7 STA &EA :\ Serial owns 6850 for 103 more calls .LDCDD \ Exit IRQ RTS :\ \ RS423 owns 6850, PE or RxRDY interupt occured \ --------------------------------------------- \ On entry, A contains ACIA status \ \ AND with ACIA IRQ mask (normally &FF) .LDCDE AND &0278 :\ LSR A :\ Move RxRDY into Carry BCC LDCEB :\ If no RxData, jump to check DCD and TxRDY \ \ Data in RxData, check for errors \ BVS LDCEB :\ If IRQ=1 (now in b6) RxIRQ must have occured, so jump to DCEB \ \ RxData but no RxIRQ, check that IRQs are actually disabled \ LDY &0250 :\ Get ACIA control setting BMI LDC7D :\ If bit 7=1, IRQs enabled so jump to read byte and insert into buffer \ \ DCE9 -> RxData, no RxIRQ, IRQs disabled \ DCE4 -> RxData and RxIRQ \ DCE2 -> No RxData \ \ Check TxRDY and DCD, if neither set, send a Serial Error Event \ -------------------------------------------------------------- .LDCEB \ Move TxRDY into Carry LSR A :\ ROR A :\ Rotate TxRDY into b7 and DCD into Carry BCS LDCB3 :\ If Data Carrier Detected, jump to DCB3 BMI LDCBF :\ If TxRDY (now in b7) jump to to DCBF to send a byte BVS LDCDD :\ b6 should always be zero by now, but if set, then jump to exit \ Issue Unknown Interupt service call \ =================================== .LDCF3 \DCF3 LDX #&05 LDX #&05 :\ JSR LF168 :\ Issue service call 5, 'Unknown Interrupt' BEQ LDCDD :\ If claimed, then jump to exit PLA :\ Otherwise drop return address from stack PLA :\ PLA :\ And restore registers TAY :\ PLA :\ TAX :\ PLA :\ STA &FC :\ Store A in IRQA JMP (&0206) :\ And pass the IRQ in to IRQ2V \************************************************************************* \* * \* VIA INTERUPTS ROUTINES * \* * \************************************************************************* \ Read System VIA interrupt flag register .LDD06 LDA LFE4D :\ BPL LDD47 :\ No System VIA interrupt, jump to check User VIA \ System VIA interupt \ AND &0279 :\ Mask with System VIA bit mask AND LFE4E :\ and interrupt enable register ROR A :\ Rotate to check for CA1 interupt (frame sync) ROR A :\ BCC LDD69 :\ No CA1 (frame sync), jump to check speech \ System VIA CA1 interupt (Frame Sync) \ DEC &0240 :\ decrement vertical sync counter LDA &EA :\ A=RS423 Timeout counter BPL LDD1E :\ if +ve then DD1E INC &EA :\ else increment it .LDD1E \load flash counter LDA &0251 :\ BEQ LDD3D :\ if 0 then system is not in use, ignore it DEC &0251 :\ else decrement counter BNE LDD3D :\ and if not 0 go on past reset routine LDX &0252 :\ else get mark period count in X LDA &0248 :\ current VIDEO ULA control setting in A LSR A :\ shift bit 0 into C to check if first colour BCC LDD34 :\ is effective if so C=0 jump to DD34 LDX &0253 :\ else get space period count in X .LDD34 \restore bit ROL A :\ EOR #&01 :\ and invert it JSR LEA00 :\ then change colour STX &0251 :\ &0251=X resetting the counter .LDD3D \Y=4 and call E494 to check and implement vertical LDY #&04 :\ JSR LE494 :\ sync event (4) if necessary LDA #&02 :\ A=2 JMP LDE6E :\ clear interrupt 1 and exit \************************************************************************* \* * \* PRINTER INTERRUPT USER VIA 1 * \* * \************************************************************************* \ Read User VIA interrupt flag register .LDD47 LDA LFE6D :\ BPL LDCF3 :\ No User VIA interrupt, jump to pass to ROMs \ User VIA interupt \ AND &0277 :\ else check for USER IRQ 1 AND LFE6E :\ ROR A :\ ROR A :\ BCC LDCF3 :\ if bit 1=0 the no interrupt 1 so DCF3 LDY &0285 :\ else get printer type DEY :\ decrement BNE LDCF3 :\ if not parallel then DCF3 LDA #&02 :\ reset interrupt 1 flag STA LFE6D :\ STA LFE6E :\ disable interrupt 1 LDX #&03 :\ and output data to parallel printer JMP LE13A :\ \************************************************************************* \* * \* SYSTEM INTERRUPT 5 Speech * \* * \************************************************************************* \ Rotate bit 5 into bit 7 .LDD69 ROL A :\ ROL A :\ ROL A :\ ROL A :\ BPL LDDCA :\ Not a Timer 2 interrupt, jump to check timers \ System VIA Timer 2 interupt - Speech interupt \ LDA #&20 :\ Prepare to clear VIA interupt LDX #&00 :\ DD71 LDX #&00 STA LFE4D :\ Clear VIA interupt STX LFE49 :\ Zero high byte of T2 Timer .LDD79 \X=8 for Speech buffer LDX #&08 :\ STX &FB :\ Prepare to loop up to four times for Speak from RAM .LDD7D \Examine Speech buffer JSR LE45B :\ ROR &02D7 :\ Shift carry into bit 7 BMI LDDC9 :\ Buffer empty, so exit TAY :\ Buffer not empty, A=first byte waiting BEQ LDD8D :\ Waiting byte=&00 (Speak, no reset), skip past JSR LEE6D :\ control speech chip BMI LDDC9 :\ if negative exit .LDD8D \Fetch Speech command byte from buffer JSR LE460 :\ STA &F5 :\ Store it JSR LE460 :\ Fetch Speech word high byte from buffer STA &F7 :\ Store it JSR LE460 :\ Fetch Speech word low byte from buffer STA &F6 :\ Store it, giving &F6/7=address to be accessed LDY &F5 :\ Y=Speech command byte BEQ LDDBB :\ SOUND &FF00 - Speak from RAM, no reset BPL LDDB8 :\ SOUND &FF01-&FF7F - Speak from RAM, with reset BIT &F5 :\ Check bit 6 of Speech command BVS LDDAB :\ SOUND &FFC0-&FFFF - Speak word number \ SOUND &FF80-&FFBF - Speak from absolute address \ &F5=command &80-&BF (b0-b3=PHROM number), &F6/7=address \ JSR LEEBB :\ Write address to speech processor BVC LDDB2 :\ Skip forward to speak from selected address \ SOUND &FFC0-&FFFF - Speak word number \ &F5=command &C0-&FF (b0-b3=PHROM number), &F6/7=word number \ .LDDAB \Multiply address by 2 to index into word table ASL &F6 :\ ROL &F7 :\ JSR LEE3B :\ Read address from specified PHROM \ Speak from PHROM address \ By now, the address in the PHROM specified in Command b0-b3 has been set \ to the start of the speech data to be voiced. \ .LDDB2 \Fetch command code, usually &50=Speak or &00=Nop LDY &0261 :\ JMP LEE7F :\ Jump to send command to speak from current address \ SOUND &FF01-&FF7F - Speak from RAM with reset \ Y=Speech command byte, &F6/7=Speech data \ Use SOUND &FF60 to send Speak External command \ \ Send command byte to Speech processor .LDDB8 JSR LEE7F :\ \ SOUND &FF00 - Speak from RAM without reset \ &6/7=Speech data \ .LDDBB \DDBB LDY &F6 LDY &F6 :\ JSR LEE7F :\ Send Speech data low byte LDY &F7 :\ DDC0 LDY &F7 JSR LEE7F :\ Send Speech data high byte LSR &FB :\ Shift loop counter BNE LDD7D :\ Loop to send up to four byte-pairs .LDDC9 \DDC9 RTS RTS :\ \*********************************************************************** \* * \* SYSTEM INTERRUPT 6 10mS Clock * \* * \************************************************************************* \ bit 6 is in carry so if clear there is no 6 int .LDDCA BCC LDE47 :\ :\ so go on to DE47 LDA #&40 :\ Clear interrupt 6 STA LFE4D :\ \UPDATE timers routine, There are 2 timer stores &292-6 and &297-B \these are updated by adding 1 to the current timer and storing the \result in the other, the direction of transfer being changed each \time of update. This ensures that at least 1 timer is valid at any call \as the current timer is only read. Other methods would cause inaccuracies \if a timer was read whilst being updated. LDA &0283 :\ get current system clock store pointer (5,or 10) TAX :\ put A in X EOR #&0F :\ and invert lo nybble (5 becomes 10 and vv) PHA :\ store A TAY :\ put A in Y :\ Carry is always set at this point .LDDD9 \get timer value LDA &0291,X :\ ADC #&00 :\ update it STA &0291,Y :\ store result in alternate DEX :\ decrement X BEQ LDDE7 :\ if 0 exit DEY :\ else decrement Y BNE LDDD9 :\ and go back and do next byte .LDDE7 \get back A PLA :\ STA &0283 :\ and store back in clock pointer, i.e. inverse previous :\ contents LDX #&05 :\ set loop pointer for countdown timer .LDDED \increment byte and if INC &029B,X :\ BNE LDDFA :\ not 0 then DDFA DEX :\ else decrement pointer BNE LDDED :\ and if not 0 do it again LDY #&05 :\ process EVENT 5 interval timer JSR LE494 :\ .LDDFA \get byte of inkey countdown timer LDA &02B1 :\ BNE LDE07 :\ if not 0 then DE07 LDA &02B2 :\ else get next byte BEQ LDE0A :\ if 0 DE0A DEC &02B2 :\ decrement 2B2 .LDE07 \and 2B1 DEC &02B1 :\ .LDE0A \read bit 7 of envelope processing byte BIT &02CE :\ BPL LDE1A :\ if 0 then DE1A INC &02CE :\ else increment to 0 CLI :\ allow interrupts JSR LEB47 :\ and do routine sound processes SEI :\ bar interrupts DEC &02CE :\ DEC envelope processing byte back to 0 .LDE1A \read speech buffer busy flag BIT &02D7 :\ BMI LDE2B :\ if set speech buffer is empty, skip routine JSR LEE6D :\ update speech system variables EOR #&A0 :\ CMP #&60 :\ BCC LDE2B :\ if result >=&60 DE2B JSR LDD79 :\ else more speech work .LDE2B \set V and C BIT LD9B7 :\ JSR LDCA2 :\ check if ACIA needs attention LDA &EC :\ check if key has been pressed ORA &ED :\ AND &0242 :\ (this is 0 if keyboard is to be ignored, else &FF) BEQ LDE3E :\ if 0 ignore keyboard SEC :\ else set carry JSR LF065 :\ and call keyboard .LDE3E \check for data in user defined printer channel JSR LE19B :\ BIT LFEC0 :\ if ADC bit 6 is set ADC is not busy BVS LDE4A :\ so DE4A RTS :\ else return \************************************************************************* \* * \* SYSTEM INTERRUPT 4 ADC end of conversion * \* * \************************************************************************* \ put original bit 4 from FE4D into bit 7 of A .LDE47 ROL A :\ BPL LDE72 :\ if not set DE72 .LDE4A \else get current ADC channel LDX &024C :\ BEQ LDE6C :\ if 0 DE6C LDA LFEC2 :\ read low data byte STA &02B5,X :\ store it in &2B6,7,8 or 9 LDA LFEC1 :\ get high data byte STA &02B9,X :\ and store it in hi byte STX &02BE :\ store in Analogue system flag marking last channel LDY #&03 :\ handle event 3 conversion complete JSR LE494 :\ DEX :\ decrement X BNE LDE69 :\ if X=0 LDX &024D :\ get highest ADC channel preseny .LDE69 \and start new conversion JSR LDE8F :\ .LDE6C \reset interrupt 4 LDA #&10 :\ .LDE6E STA LFE4D :\ RTS :\ and return \************************************************************************* \* * \* SYSTEM INTERRUPT 0 Keyboard * \* * \************************************************************************* \ get original bit 0 in bit 7 position .LDE72 ROL A :\ ROL A :\ ROL A :\ ROL A :\ BPL LDE7F :\ if bit 7 clear not a keyboard interrupt JSR LF065 :\ else scan keyboard LDA #&01 :\ A=1 BNE LDE6E :\ and off to reset interrupt and exit .LDE7F JMP LDCF3 :\ \************** exit routine ********************************************* \ restore registers PLA :\ TAY :\ PLA :\ TAX :\ PLA :\ STA &FC :\ store A \************************************************************************* \* * \* IRQ2V default entry * \* * \************************************************************************* LDA &FC :\ get back original value of A RTI :\ and return to calling routine \************************************************************************* \* * \* OSBYTE 17 Start conversion * \* * \************************************************************************* \ set last channel to finish conversion .LDE8C STY &02BE :\ .LDE8F \if X<4 then CPX #&05 :\ BCC LDE95 :\ DE95 LDX #&04 :\ else X=4 .LDE95 \store it as current ADC channel STX &024C :\ LDY &024E :\ get conversion type DEY :\ decrement TYA :\ A=Y AND #&08 :\ and it with 08 CLC :\ clear carry ADC &024C :\ add to current ADC SBC #&00 :\ -1 STA LFEC0 :\ store to the A/D control panel RTS :\ and return \ point to start of string @&C300 .LDEA9 LDA #&C3 :\ .LDEAB \store it STA &FE :\ LDA #&00 :\ point to lo byte STA &FD :\ store it and start loop@ .LDEB1 \print character in string INY :\ LDA (&FD),Y :\ pointed to by &FD/E JSR OSASCI :\ print it expanding Carriage returns TAX :\ store A in X BNE LDEB1 :\ and loop again if not =0 RTS :\ else exit \*********** OSBYTE 129 TIMED ROUTINE ****************************** \ON ENTRY TIME IS IN X,Y \ store time in INKEY countdown timer .LDEBB STX &02B1 :\ STY &02B2 :\ which is decremented every 10ms LDA #&FF :\ A=&FF to flag timed wait BNE LDEC7 :\ goto DEC7 \************************************************************************** \************************************************************************** \** ** \** OSRDCH Default entry point ** \** ** \** RDCHV entry point read a character ** \** ** \************************************************************************** \************************************************************************** .LDEC5 \A=0 to flag wait forever LDA #&00 :\ .LDEC7 \store entry value of A STA &E6 :\ TXA :\ save X and Y PHA :\ TYA :\ PHA :\ LDY &0256 :\ get *EXEC file handle BEQ LDEE6 :\ if 0 (not open) then DEE6 SEC :\ set carry ROR &EB :\ set bit 7 of CFS active flag to prevent clashes JSR OSBGET :\ get a byte from the file PHP :\ push processor flags to preserve carry LSR &EB :\ restore &EB PLP :\ get back flags BCC LDF03 :\ and if carry clear, character found so exit via DF03 LDA #&00 :\ else A=00 as EXEC file empty STA &0256 :\ store it in exec file handle JSR OSFIND :\ and close file via OSFIND .LDEE6 \check ESCAPE flag, if bit 7 set Escape pressed BIT &FF :\ BMI LDF00 :\ so off to DF00 LDX &0241 :\ else get current input buffer number JSR LE577 :\ get a byte from input buffer BCC LDF03 :\ and exit if character returned BIT &E6 :\ (E6=0 or FF) BVC LDEE6 :\ if entry was OSRDCH not timed keypress, so go back and :\ do it again i.e. perform GET function LDA &02B1 :\ else check timers ORA &02B2 :\ BNE LDEE6 :\ and if not zero go round again BCS LDF05 :\ else exit .LDF00 \DEFE BCS &DF05 SEC :\ DF00 SEC LDA #&1B :\ DF01 LDA #&1B .LDF03 STA &E6 :\ DF03 STA &E6 .LDF05 PLA :\ DF05 PLA TAY :\ DF06 TAY PLA :\ DF07 PLA TAX :\ DF08 TAX LDA &E6 :\ DF09 LDA &E6 RTS :\ DF0B RTS .LDF0C EQUS ")C(":EQUB 0 .LDF10 EQUS "." :EQUB LE031 DIV 256:EQUB LE031 AND 255:EQUB &05 :\ XY=>string, FSC &05 EQUS "FX" :EQUB LE342 DIV 256:EQUB LE342 AND 255:EQUB &FF :\ XY=>string EQUS "BASIC" :EQUB LE018 DIV 256:EQUB LE018 AND 255:EQUB &00 :\ (&F2),Y=>string EQUS "CAT" :EQUB LE031 DIV 256:EQUB LE031 AND 255:EQUB &05 :\ XY=>string, FSC &05 EQUS "CODE" :EQUB LE348 DIV 256:EQUB LE348 AND 255:EQUB &88 :\ X,Y=parameters, OSBYTE &88 EQUS "EXEC" :EQUB LF68D DIV 256:EQUB LF68D AND 255:EQUB &00 :\ (&F2),Y=>string EQUS "HELP" :EQUB LF0B9 DIV 256:EQUB LF0B9 AND 255:EQUB &FF :\ XY=>string EQUS "KEY" :EQUB LE327 DIV 256:EQUB LE327 AND 255:EQUB &FF :\ XY=>string EQUS "LOAD" :EQUB LE23C DIV 256:EQUB LE23C AND 255:EQUB &00 :\ (&F2),Y=>string EQUS "LINE" :EQUB LE659 DIV 256:EQUB LE659 AND 255:EQUB &01 :\ XY=>string EQUS "MOTOR" :EQUB LE348 DIV 256:EQUB LE348 AND 255:EQUB &89 :\ X,Y=parameters, OSBYTE &89 EQUS "OPT" :EQUB LE348 DIV 256:EQUB LE348 AND 255:EQUB &8B :\ X,Y=parameters, OSBYTE &8B EQUS "RUN" :EQUB LE031 DIV 256:EQUB LE031 AND 255:EQUB &04 :\ XY=>string, FSC &04 EQUS "ROM" :EQUB LE348 DIV 256:EQUB LE348 AND 255:EQUB &8D :\ X,Y=parameters, OSBYTE &8D EQUS "SAVE" :EQUB LE23E DIV 256:EQUB LE23E AND 255:EQUB &00 :\ (&F2),Y=>string EQUS "SPOOL" :EQUB LE281 DIV 256:EQUB LE281 AND 255:EQUB &00 :\ (&F2),Y=>string EQUS "TAPE" :EQUB LE348 DIV 256:EQUB LE348 AND 255:EQUB &8C :\ X,Y=parameters, OSBYTE &8C EQUS "TV" :EQUB LE348 DIV 256:EQUB LE348 AND 255:EQUB &90 :\ X,Y=parameters, OSBYTE &90 EQUS "" :EQUB LE031 DIV 256:EQUB LE031 AND 255:EQUB &03 :\ XY=>string, FSC &03 EQUB 0 \ OSCLI Handler \ ============= .LDF89 \ Command routines are entered with XY=>command tail, A=table parameter, \ &F2/3,&E6=>start of command string \ If table parameter if <&80, F2/3,Y converted to XY before entering \************************************************************************* \* CLI - COMMAND LINE INTERPRETER * \* * \* ENTRY, XY=>Command line * \* EXIT, All registers corrupted * \* [ A=13 - unterminated string ] * \************************************************************************* \; STX &F2 :\ Store XY in &F2/3 STY &F3 :\ DF8B STY &F3 LDA #&08 :\ DF8D LDA #&08 JSR LE031 :\ Inform filing system CLI being processed LDY #&00 :\ Check the line is correctly terminated .LDF94 LDA (&F2),Y :\ DF94 LDA (&F2),Y CMP #&0D :\ Loop until CR is found BEQ LDF9E :\ DF98 BEQ &DF9E INY :\ Move to next character BNE LDF94 :\ Loop back if less than 256 bytes long RTS :\ Exit if string > 255 characters .LDF9E \; String is terminated - skip prepended spaces and '*'s LDY #&FF :\ DF9E LDY #&FF .LDFA0 JSR LE039 :\ Skip any spaces BEQ LE017 :\ Exit if at CR CMP #&2A :\ Is this character '*'? BEQ LDFA0 :\ Loop back to skip it, and check for spaces again JSR LE03A :\ Skip any more spaces BEQ LE017 :\ Exit if at CR CMP #&7C :\ Is it '|' - a comment BEQ LE017 :\ Exit if so CMP #&2F :\ Is it '/' - pass straight to filing system BNE LDFBE :\ Jump forward if not INY :\ Move past the '/' JSR LE009 :\ Convert &F2/3,Y->XY, ignore returned A LDA #&02 :\ 2=RunSlashCommand BNE LE031 :\ Jump to pass to FSCV .LDFBE \; \; Look command up in command table STY &E6 :\ Store offset to start of command LDX #&00 :\ DFC0 LDX #&00 BEQ LDFD7 :\ DFC2 BEQ &DFD7 .LDFC4 \; EOR LDF10,X :\ DFC4 EOR &DF10,X AND #&DF :\ DFC7 AND #&DF BNE LDFE2 :\ DFC9 BNE &DFE2 INY :\ DFCB INY CLC :\ DFCC CLC .LDFCD \; BCS LDFF4 :\ DFCD BCS &DFF4 INX :\ DFCF INX LDA (&F2),Y :\ DFD0 LDA (&F2),Y JSR LE4E3 :\ DFD2 JSR &E4E3 BCC LDFC4 :\ DFD5 BCC &DFC4 .LDFD7 \; LDA LDF10,X :\ DFD7 LDA &DF10,X BMI LDFF2 :\ DFDA BMI &DFF2 LDA (&F2),Y :\ DFDC LDA (&F2),Y CMP #&2E :\ DFDE CMP #&2E BEQ LDFE6 :\ DFE0 BEQ &DFE6 .LDFE2 CLC :\ DFE2 CLC LDY &E6 :\ DFE3 LDY &E6 DEY :\ DFE5 DEY .LDFE6 INY :\ DFE6 INY INX :\ DFE7 INX .LDFE8 INX :\ DFE8 INX LDA LDF0E,X :\ DFE9 LDA &DF0E,X BEQ LE021 :\ DFEC BEQ &E021 BPL LDFE8 :\ DFEE BPL &DFE8 BMI LDFCD :\ DFF0 BMI &DFCD .LDFF2 \ INX :\ DFF2 INX INX :\ DFF3 INX .LDFF4 \; DEX :\ DFF4 DEX DEX :\ DFF5 DEX PHA :\ DFF6 PHA LDA LDF11,X :\ DFF7 LDA &DF11,X PHA :\ DFFA PHA JSR LE03A :\ DFFB JSR &E03A CLC :\ DFFE CLC PHP :\ DFFF PHP JSR LE004 :\ E000 JSR &E004 RTI :\ Jump to routine .LE004 LDA LDF12,X :\ Get table parameter BMI LE017 :\ If >=&80, number follow .LE009 \ ; else string follows TYA :\ Pass Y line offset to A for later LDY LDF12,X :\ Get looked-up parameter from table .LE00D \ Convert &F2/3,A to XY, put Y in A CLC :\ E00D CLC ADC &F2 :\ E00E ADC &F2 TAX :\ E010 TAX TYA :\ Pass supplied Y into A LDY &F3 :\ E012 LDY &F3 BCC LE017 :\ E014 BCC &E017 INY :\ E016 INY .LE017 \ RTS :\ E017 RTS \ *BASIC \ ====== .LE018 \ *BASIC \ ====== LDX &024B :\ Get BASIC ROM number BMI LE021 :\ If none set, jump to pass command on SEC :\ Set Carry = not entering from RESET JMP LDBE7 :\ Enter language rom in X .LE021 \ Pass command on to other ROMs and to filing system LDY &E6 :\ Restore pointer to start of command LDX #&04 :\ 4=UnknownCommand JSR LF168 :\ Pass to sideways ROMs BEQ LE017 :\ If claimed, exit LDA &E6 :\ Restore pointer to start of command JSR LE00D :\ Convert &F2/3,A to XY, ignore returned A LDA #&03 :\ 3=PassCommandToFilingSystem .LE031 \ Pass to current filing system JMP (&021E) :\ E031 JMP (&021E) .LE034 ASL A :\ E034 ASL A AND #&01 :\ E035 AND #&01 BPL LE031 :\ E037 BPL &E031 .LE039 \ Skip spaces INY :\ E039 INY .LE03A LDA (&F2),Y :\ E03A LDA (&F2),Y CMP #&20 :\ E03C CMP #&20 BEQ LE039 :\ E03E BEQ &E039 .LE040 CMP #&0D :\ E040 CMP #&0D RTS :\ E042 RTS .LE043 BCC LE03A :\ E043 BCC &E03A .LE045 JSR LE03A :\ E045 JSR &E03A CMP #&2C :\ E048 CMP #&2C BNE LE040 :\ E04A BNE &E040 INY :\ E04C INY RTS :\ E04D RTS .LE04E JSR LE03A :\ E04E JSR &E03A JSR LE07D :\ E051 JSR &E07D BCC LE08D :\ E054 BCC &E08D .LE056 STA &E6 :\ E056 STA &E6 JSR LE07C :\ E058 JSR &E07C BCC LE076 :\ E05B BCC &E076 TAX :\ E05D TAX LDA &E6 :\ E05E LDA &E6 ASL A :\ E060 ASL A BCS LE08D :\ E061 BCS &E08D ASL A :\ E063 ASL A BCS LE08D :\ E064 BCS &E08D ADC &E6 :\ E066 ADC &E6 BCS LE08D :\ E068 BCS &E08D ASL A :\ E06A ASL A BCS LE08D :\ E06B BCS &E08D STA &E6 :\ E06D STA &E6 TXA :\ E06F TXA ADC &E6 :\ E070 ADC &E6 BCS LE08D :\ E072 BCS &E08D BCC LE056 :\ E074 BCC &E056 .LE076 LDX &E6 :\ E076 LDX &E6 CMP #&0D :\ E078 CMP #&0D SEC :\ E07A SEC RTS :\ E07B RTS .LE07C INY :\ E07C INY .LE07D LDA (&F2),Y :\ E07D LDA (&F2),Y CMP #&3A :\ E07F CMP #&3A BCS LE08D :\ E081 BCS &E08D CMP #&30 :\ E083 CMP #&30 BCC LE08D :\ E085 BCC &E08D AND #&0F :\ E087 AND #&0F RTS :\ E089 RTS .LE08A JSR LE045 :\ E08A JSR &E045 .LE08D CLC :\ E08D CLC RTS :\ E08E RTS .LE08F JSR LE07D :\ E08F JSR &E07D BCS LE0A2 :\ E092 BCS &E0A2 AND #&DF :\ E094 AND #&DF CMP #&47 :\ E096 CMP #&47 BCS LE08A :\ E098 BCS &E08A CMP #&41 :\ E09A CMP #&41 BCC LE08A :\ E09C BCC &E08A PHP :\ E09E PHP SBC #&37 :\ E09F SBC #&37 PLP :\ E0A1 PLP .LE0A2 INY :\ E0A2 INY RTS :\ E0A3 RTS \************************************************************************** \************************************************************************** \** ** \** OSWRCH HANDLER ** \** ** \** Output a character to current output streams ** \** ** \************************************************************************** \************************************************************************** .LE0A4 \ WRCH control routine \ ==================== PHA :\ Save all registers TXA :\ E0A5 TXA PHA :\ E0A6 PHA TYA :\ E0A7 TYA PHA :\ E0A8 PHA TSX :\ E0A9 TSX LDA &0103,X :\ Get A back from stack PHA :\ Save A BIT &0260 :\ Check OSWRCH interception flag BPL LE0BB :\ Not set, skip interception call TAY :\ Pass character to Y LDA #&04 :\ A=4 for OSWRCH call JSR LE57E :\ Call interception code BCS LE10D :\ If claimed, jump past to exit .LE0BB CLC :\ Prepare to not send this to printer LDA #&02 :\ Check output destination BIT &027C :\ Is VDU driver disabled? BNE LE0C8 :\ Yes, skip past VDU driver PLA :\ Get character back PHA :\ Resave character JSR LC4C0 :\ Call VDU driver .LE0C8 ; On exit, C=1 if character to be sent to printer LDA #&08 :\ Check output destination BIT &027C :\ Is printer seperately enabled? BNE LE0D1 :\ Yes, jump to call printer driver BCC LE0D6 :\ Carry clear, don't sent to printer .LE0D1 PLA :\ Get character back PHA :\ Resave character JSR LE114 :\ Call printer driver .LE0D6 LDA &027C :\ Check output destination ROR A :\ Is serial output enabled? BCC LE0F7 :\ No, skip past serial output LDY &EA :\ Get serial timout counter DEY :\ Decrease counter BPL LE0F7 :\ Timed out, skip past serial code PLA :\ Get character back PHA :\ Resave character PHP :\ Save IRQs SEI :\ Disable IRQs LDX #&02 :\ X=2 for serial output buffer PHA :\ Save character JSR LE45B :\ Examine serial output buffer BCC LE0F0 :\ Buffer not full, jump to send character JSR LE170 :\ Wait for buffer to empty a bit .LE0F0 PLA :\ Get character back LDX #&02 :\ X=2 for serial output buffer JSR LE1F8 :\ Send character to serial output buffer PLP :\ Restore IRQs .LE0F7 LDA #&10 :\ Check output destination BIT &027C :\ Is SPOOL output disabled? BNE LE10D :\ Yes, skip past SPOOL output LDY &0257 :\ Get SPOOL handle BEQ LE10D :\ If not open, skip past SPOOL output PLA :\ Get character back PHA :\ Resave character SEC :\ E105 SEC ROR &EB :\ Set RFS/CFS's 'spooling' flag JSR OSBPUT :\ Write character to SPOOL channel LSR &EB :\ Reset RFS/CFS's 'spooling' flag .LE10D PLA :\ Restore all registers PLA :\ E10E PLA TAY :\ E10F TAY PLA :\ E110 PLA TAX :\ E111 TAX PLA :\ E112 PLA RTS :\ Exit .LE114 \************************************************************************* \* * \* PRINTER DRIVER * \* * \************************************************************************* \A=character to print BIT &027C :\ if bit 6 of VDU byte =1 printer is disabled BVS LE139 :\ so E139 CMP &0286 :\ compare with printer ignore character BEQ LE139 :\ if the same E139 .LE11E PHP :\ else save flags SEI :\ bar interrupts TAX :\ X=A LDA #&04 :\ A=4 BIT &027C :\ read bit 2 'disable printer driver' BNE LE138 :\ if set printer is disabled so exit E138 TXA :\ else A=X LDX #&03 :\ X=3 JSR LE1F8 :\ and put character in printer buffer BCS LE138 :\ if carry set on return exit, buffer not full (empty?) BIT &02D2 :\ else check buffer busy flag if 0 BPL LE138 :\ then E138 to exit JSR LE13A :\ else E13A to open printer cahnnel .LE138 PLP :\ get back flags .LE139 RTS :\ and exit .LE13A LDA &0285 :\ check printer destination BEQ LE1AD :\ if 0 then E1AD clear printer buffer and exit CMP #&01 :\ if parallel printer not selected BNE LE164 :\ E164 JSR LE460 :\ else read a byte from the printer buffer ROR &02D2 :\ if carry is set then 2d2 is -ve BMI LE190 :\ so return via E190 LDY #&82 :\ else enable interrupt 1 of the external VIA STY LFE6E :\ STA LFE61 :\ pass code to centronics port LDA LFE6C :\ pulse CA2 line to generate STROBE signal AND #&F1 :\ to advise printer that ORA #&0C :\ valid data is STA LFE6C :\ waiting ORA #&0E :\ STA LFE6C :\ BNE LE190 :\ then exit .LE164 \********* serial printer ********************************************* CMP #&02 :\ is it Serial printer?? BNE LE191 :\ if not E191 LDY &EA :\ else is RS423 in use by cassette?? DEY :\ BPL LE1AD :\ if so E1AD to flush buffer LSR &02D2 :\ else clear buffer busy flag .LE170 LSR &024F :\ and RS423 busy flag .LE173 JSR LE741 :\ count buffer if C is clear on return BCC LE190 :\ no room in buffer so exit LDX #&20 :\ else .LE17A LDY #&9F :\ \************************************************************************* \* * \* OSBYTE 156 update ACIA setting and RAM copy * \* * \************************************************************************* \on entry PHP :\ push flags SEI :\ bar interrupts TYA :\ A=Y STX &FA :\ &FA=X AND &0250 :\ A=old value AND Y EOR X EOR &FA :\ LDX &0250 :\ get old value in X .LE189 STA &0250 :\ put new value in STA LFE08 :\ and store to ACIA control register PLP :\ get back flags .LE190 RTS :\ and exit .LE191 \************ printer is neither serial or parallel so its user type ***** CLC :\ clear carry LDA #&01 :\ A=1 JSR LE1A2 :\ \************************************************************************* \* * \* OSBYTE 123 Warn printer driver going dormant * \* * \************************************************************************* ROR &02D2 :\ mark printer buffer empty for osbyte .LE19A RTS :\ and exit .LE19B BIT &02D2 :\ if bit 7 is set buffer is empty BMI LE19A :\ so exit LDA #&00 :\ else A=0 .LE1A2 LDX #&03 :\ X=3 .LE1A4 LDY &0285 :\ Y=printer destination JSR LE57E :\ to JMP (NETV) JMP (&0222) :\ jump to PRINT VECTOR for special routines .LE1AD \*************** Buffer handling ***************************************** \ ;X=buffer number \ ;Buffer number Address Flag Out pointer In pointer \ ;0=Keyboard 3E0-3FF 2CF 2D8 2E1 \ ;1=RS423 Input A00-AFF 2D0 2D9 2E2 \ ;2=RS423 output 900-9BF 2D1 2DA 2E3 \ ;3=printer 880-8BF 2D2 2DB 2E4 \ ;4=sound0 840-84F 2D3 2DC 2E5 \ ;5=sound1 850-85F 2D4 2DD 2E6 \ ;6=sound2 860-86F 2D5 2DE 2E7 \ ;7=sound3 870-87F 2D6 2DF 2E8 \ ;8=speech 8C0-8FF 2D7 2E0 2E9 CLC :\ clear carry .LE1AE PHA :\ save A PHP :\ save flags SEI :\ set interrupts BCS LE1BB :\ if carry set on entry then E1BB LDA LE9AD,X :\ else get byte from baud rate/sound data table BPL LE1BB :\ if +ve the E1BB JSR LECA2 :\ else clear sound data .LE1BB SEC :\ set carry ROR &02CF,X :\ rotate buffer flag to show buffer empty CPX #&02 :\ if X>1 then its not an input buffer BCS LE1CB :\ so E1CB LDA #&00 :\ else Input buffer so A=0 STA &0268 :\ store as length of key string STA &026A :\ and length of VDU queque .LE1CB JSR LE73B :\ then enter via count purge vector any user routines PLP :\ restore flags PLA :\ restore A RTS :\ and exit \************************************************************************* \* * \* COUNT PURGE VECTOR DEFAULT ENTRY * \* * \************************************************************************* \on entry if V set clear buffer \ if C set get space left \ else get bytes used BVC LE1DA :\ if bit 6 is set then E1DA LDA &02D8,X :\ else start of buffer=end of buffer STA &02E1,X :\ RTS :\ and exit .LE1DA PHP :\ push flags SEI :\ bar interrupts PHP :\ push flags SEC :\ set carry LDA &02E1,X :\ get end of buffer SBC &02D8,X :\ subtract start of buffer BCS LE1EA :\ if carry caused E1EA SEC :\ set carry SBC LE447,X :\ subtract buffer start offset (i.e. add buffer length) .LE1EA PLP :\ pull flags BCC LE1F3 :\ if carry clear E1F3 to exit CLC :\ clear carry ADC LE447,X :\ adc to get bytes used EOR #&FF :\ and invert to get space left .LE1F3 LDY #&00 :\ Y=0 TAX :\ X=A PLP :\ get back flags RTS :\ and exit .LE1F8 \********** enter byte in buffer, wait and flash lights if full ********** SEI :\ prevent interrupts JSR LE4B0 :\ enter a byte in buffer X BCC LE20D :\ if successful exit JSR LE9EA :\ else switch on both keyboard lights PHP :\ push p PHA :\ push A JSR LEEEB :\ switch off unselected LEDs PLA :\ get back A PLP :\ and flags BMI LE20D :\ if return is -ve Escape pressed so exit CLI :\ else allow interrupts BCS LE1F8 :\ if byte didn't enter buffer go and try it again .LE20D RTS :\ then return .LE20E PHA :\ LDA #&00 :\ A=0 STA &02EE,X :\ clear osfile control block workspace STA &02EF,X :\ STA &02F0,X :\ STA &02F1,X :\ PLA :\ get back A RTS :\ and exit \*********** shift through osfile control block ************************** \ &E6=Y .LE21F STY &E6 :\ ROL A :\ A=A*2 ROL A :\ *4 ROL A :\ *8 ROL A :\ *16 LDY #&04 :\ Y=4 .LE227 \A=A*32 ROL A :\ ROL &02EE,X :\ shift bit 7 of A into shift register ROL &02EF,X :\ and ROL &02F0,X :\ shift ROL &02F1,X :\ along BCS LE267 :\ if carry set on exit then register has overflowed :\ so bad address error DEY :\ decrement Y BNE LE227 :\ and if Y>0 then do another shift LDY &E6 :\ get back original Y RTS :\ and exit \************************************************************************* \* * \* *LOAD ENTRY * \* * \************************************************************************* \ signal that load is being performed LDA #&FF :\ \************************************************************************* \* * \* *SAVE ENTRY * \* * \************************************************************************* \on entry A=0 for save &ff for load STX &F2 :\ store address of rest of command line STY &F3 :\ STX &02EE :\ x and Y are stored in OSfile control block STY &02EF :\ PHA :\ Push A LDX #&02 :\ X=2 JSR LE20E :\ clear the shift register LDY #&FF :\ Y=255 STY &02F4 :\ store im 2F4 INY :\ increment Y JSR LEA1D :\ and call GSINIT to prepare for reading text line .LE257 \read a code from text line if OK read next JSR LEA2F :\ BCC LE257 :\ until end of line reached PLA :\ get back A without stack changes PHA :\ BEQ LE2C2 :\ IF A=0 (SAVE) E2C2 JSR LE2AD :\ set up file block BCS LE2A0 :\ if carry set do OSFILE BEQ LE2A5 :\ else if A=0 goto OSFILE .LE267 BRK :\ EQUB &FC :\ EQUB &42 :\ error ADC (&64,X) :\ JSR &6461 :\ STZ &72 :\ ADC &73 :\ EQUB &73 :\ BRK :\ \************************************************************************* \* * \* OSBYTE 119 ENTRY * \* CLOSE SPOOL/ EXEC FILES * \* * \************************************************************************* .LE275 \X=10 issue *SPOOL/EXEC files warning LDX #&10 :\ JSR LF168 :\ and issue call BEQ LE29F :\ if a rom accepts and issues a 0 then E29F to return JSR LF68B :\ else close the current exec file LDA #&00 :\ A=0 \************************************************************************** \* * \* *SPOOL * \* * \************************************************************************** PHP :\ if A=0 file is closed so STY &E6 :\ Store Y LDY &0257 :\ get file handle STA &0257 :\ store A as file handle BEQ LE28F :\ if Y<>0 then E28F JSR OSFIND :\ else close file via osfind .LE28F \get back original Y LDY &E6 :\ PLP :\ pull flags BEQ LE29F :\ if A=0 on entry then exit LDA #&80 :\ else A=&80 JSR OSFIND :\ to open file Y for output TAY :\ Y=A BEQ LE310 :\ and if this is =0 then E310 BAD COMMAND ERROR STA &0257 :\ store file handle .LE29F \and exit RTS :\ \ if NE then BAD COMMAND error .LE2A0 BNE LE310 :\ INC &02F4 :\ increment 2F4 to 00 .LE2A5 \X=&EE LDX #&EE :\ LDY #&02 :\ Y=&02 PLA :\ get back A JMP OSFILE :\ and JUMP to OSFILE \**** check for hex digit ************************************************ \ look for NEWline .LE2AD JSR LE03A :\ JSR LE08F :\ carry is set if it finds hex digit BCC LE2C1 :\ so E2C1 exit JSR LE20E :\ clear shift register \************** shift byte into control block *************************** .LE2B8 \shift lower nybble of A into shift register JSR LE21F :\ JSR LE08F :\ then check for Hex digit BCS LE2B8 :\ if found then do it again SEC :\ else set carry .LE2C1 \and exit RTS :\ \**************; set up OSfile control block **************************** \ X=0A .LE2C2 LDX #&0A :\ JSR LE2AD :\ BCC LE310 :\ if no hex digit found EXIT via BAD Command error CLV :\ clear bit 6 \******************READ file length from text line************************ LDA (&F2),Y :\ read next byte from text line CMP #&2B :\ is it '+' BNE LE2D4 :\ if not assume its a last byte address so e2d4 BIT LD9B7 :\ else set V and M flags INY :\ increment Y to point to hex group .LE2D4 \X=E LDX #&0E :\ JSR LE2AD :\ BCC LE310 :\ if carry clear no hex digit so exit via error PHP :\ save flags BVC LE2ED :\ if V set them E2ED explicit end address found LDX #&FC :\ else X=&FC CLC :\ clear carry .LE2E1 \and add length data to start address LDA &01FC,X :\ ADC &0200,X :\ STA &0200,X :\ INX :\ BNE LE2E1 :\ repeat until X=0 .LE2ED \X=3 LDX #&03 :\ .LE2EF \copy start adddress to load and execution addresses LDA &02F8,X :\ STA &02F4,X :\ STA &02F0,X :\ DEX :\ BPL LE2EF :\ PLP :\ get back flag BEQ LE2A5 :\ if end of command line reached then E2A5 :\ to do osfile LDX #&06 :\ else set up execution address JSR LE2AD :\ BCC LE310 :\ if error BAD COMMAND BEQ LE2A5 :\ and if end of line reached do OSFILE LDX #&02 :\ else set up load address JSR LE2AD :\ BCC LE310 :\ if error BAD command BEQ LE2A5 :\ else on end of line do OSFILE :\ anything else is an error!!!! \******** Bad command error ************************************ .LE310 BRK :\ INC &6142,X :\ error number :\ STZ &20 :\ E31D BRK EQUB &63 :\ EQUB &6F :\ ADC &616D :\ ROR &0064 :\ EQUB &FB :\ EQUB &42 :\ ADC (&64,X) :\ E326 BRK JSR &656B :\ ADC &2000,Y :\ \************************************************************************* \* * \* *KEY ENTRY * \* * \************************************************************************* LSR &90E0 :\ if not valid number give error SBC (&E0),Y :\ if key number greater than 15 BPL LE2DF :\ if greater then give error SBC &4520 :\ otherwise skip commas, and check for CR CPX #&08 :\ save flags for later LDX &0B10 :\ get pointer to top of existing key strings TYA :\ save Y PHA :\ to preserve text pointer JSR LE3D1 :\ set up soft key definition PLA :\ get back Y TAY :\ PLP :\ and flags BNE LE377 :\ if CR found return else E377 to set up new string RTS :\ else return to set null string \************************************************************************* \* * \* *FX OSBYTE * \* * \************************************************************************* \ A=number JSR LE04E :\ convert the number to binary BCC LE310 :\ if bad number call bad command TXA :\ save X \************************************************************************* \* * \* *CODE *MOTOR *OPT *ROM *TAPE *TV * \* * \************************************************************************* \ :\ enter codes *CODE &88 \ *MOTOR &89 \ &8A \ *OPT &8B \ *TAPE &8C \ *ROM &8D \ &8E \ &8F \ *TV &90 PHA :\ save A LDA #&00 :\ clear &E4/E5 STA &E5 :\ STA &E4 :\ JSR LE043 :\ skip commas and check for newline (CR) BEQ LE36C :\ if CR found E36C JSR LE04E :\ convert character to binary BCC LE310 :\ if bad character bad command error STX &E5 :\ else save it JSR LE045 :\ skip comma and check CR BEQ LE36C :\ if CR then E36C JSR LE04E :\ get another parameter BCC LE310 :\ if bad error STX &E4 :\ else store in E4 JSR LE03A :\ now we must have a newline BNE LE310 :\ if none then output an error .LE36C LDY &E4 :\ Y=third osbyte parameter LDX &E5 :\ X=2nd PLA :\ A=first JSR OSBYTE :\ call osbyte BVS LE310 :\ if V set on return then error RTS :\ else RETURN .LE377 \********* *KEY CONTINUED ************************************************ \ :\ X points to last byte of current key definitions SEC :\ JSR LEA1E :\ look for '"' on return bit 6 E4=1 bit 7=1 if '"'found .LE37B :\ this is a GSINIT call without initial CLC JSR LEA2F :\ call GSREAD carry is set if end of line found BCS LE388 :\ E388 to deal with end of line INX :\ point to first byte of new key definition BEQ LE31D :\ if X=0 buffer WILL overflow so exit with BAD KEY error STA &0B00,X :\ store character BCC LE37B :\ and loop to get next byte if end of line not found .LE388 BNE LE31D :\ if Z clear then no matching found or for some :\ other reason line doesn't terminate properly PHP :\ else if all OK save flags SEI :\ bar interrupts JSR LE3D1 :\ and move string LDX #&10 :\ set loop counter .LE391 CPX &E6 :\ if key being defined is found BEQ LE3A3 :\ then skip rest of loop LDA &0B00,X :\ else get start of string X CMP &0B00,Y :\ compare with start of string Y BNE LE3A3 :\ if not the same then skip rest of loop LDA &0B10 :\ else store top of string definition STA &0B00,X :\ in designated key pointer .LE3A3 DEX :\ decrement loop pointer X BPL LE391 :\ and do it all again PLP :\ get back flags RTS :\ and exit .LE3A8 \*********** set string lengths ***************************************** PHP :\ push flags SEI :\ bar interrupts LDA &0B10 :\ get top of currently defined strings SEC :\ SBC &0B00,Y :\ subtract to get the number of bytes in strings :\ above end of string Y STA &FB :\ store this TXA :\ save X PHA :\ LDX #&10 :\ and X=16 .LE3B7 LDA &0B00,X :\ get start offset (from B00) of key string X SEC :\ SBC &0B00,Y :\ subtract offset of string we are working on BCC LE3C8 :\ if carry clear (B00+Y>B00+X) or BEQ LE3C8 :\ result (in A)=0 CMP &FB :\ or greater or equal to number of bytes above :\ string we are working on BCS LE3C8 :\ then E3C8 .LE3C6 STA &FB :\ else store A in &FB .LE3C8 DEX :\ point to next lower key offset BPL LE3B7 :\ and if 0 or +ve go back and do it again PLA :\ else get back value of X TAX :\ LDA &FB :\ get back latest value of A PLP :\ pull flags RTS :\ and return .LE3D1 \*********** set up soft key definition ********************************* PHP :\ push P SEI :\ bar interrupts TXA :\ save X PHA :\ push A LDY &E6 :\ get key number JSR LE3A8 :\ and set up &FB LDA &0B00,Y :\ get start of string TAY :\ put it in Y CLC :\ clear carry ADC &FB :\ add number of bytes above string TAX :\ put this in X STA &FA :\ and store it LDA &0268 :\ check number of bytes left to remove from key buffer :\ if not 0 key is being used (definition expanded so :\ error. This stops *KEY 1 "*key1 FRED" etc. BEQ LE3F6 :\ if not in use continue BRK :\ PLX :\ error number EQUB &4B :\ ADC &79 :\ JSR &6E69 :\ JSR &7375 :\ ADC &00 :\ .LE3F6 DEC &0284 :\ decrement consistence flag to &FF to warn that key :\ definitions are being changed PLA :\ pull A SEC :\ SBC &FA :\ subtract &FA STA &FA :\ and re store it BEQ LE40D :\ if 0 then E40D .LE401 LDA &0B01,X :\ else move string STA &0B01,Y :\ from X to Y INY :\ INX :\ DEC &FA :\ for length of string BNE LE401 :\ .LE40D TYA :\ store end of moved string(s) PHA :\ LDY &E6 :\ get back key number LDX #&10 :\ point at top of last string .LE413 LDA &0B00,X :\ get this value CMP &0B00,Y :\ compare it with start of new or re defined key BCC LE422 :\ if less then E422 BEQ LE422 :\ if = then E422 SBC &FB :\ shift key definitions accordingly STA &0B00,X :\ .LE422 DEX :\ point to next lowest string def BPL LE413 :\ and if =>0 then loop and do it again LDA &0B10 :\ else make top of key definitions STA &0B00,Y :\ the start of our key def PLA :\ get new end of strings STA &0B10 :\ and store it TAX :\ put A in X INC &0284 :\ reset consistency flag PLP :\ restore flags RTS :\ and exit .LE435 \**************** BUFFER ADDRESS HI LOOK UP TABLE ************************ EQUB &03 :\ keyboard ASL A :\ rs423 input PHP :\ rs423 output EQUB &07 :\ printer EQUB &07 :\ sound 0 EQUB &07 :\ sound 1 EQUB &07 :\ sound 2 EQUB &07 :\ sound 3 ORA #&00 :\ speech \**************** BUFFER ADDRESS LO LOOK UP TABLE ************************ BRK :\ E43F DB &00 CPY #&C0 :\ E440 DB &C0 BVC LE4A4 :\ E442 DB &50 BVS LE3C6 :\ E444 DB &70 BRK :\ E446 DB &00 .LE447 \**************** BUFFER START ADDRESS OFFSET **************************** CPX #&00 :\ E447 DB &E0 RTI :\ E449 DB &40 CPY #&F0 :\ E44A DB &C0 BEQ LE43E :\ E44C DB &F0 BEQ LE410 :\ E44E DB &F0 .LE450 \******* get nominal buffer addresses in &FA/B ************************** \ :\ ON ENTRY X=buffer number \ :\ Buffer number Address Flag Out pointer In pointer \ :\ 0=Keyboard 3E0-3FF 2CF 2D8 2E1 \ :\ 1=RS423 Input A00-AFF 2D0 2D9 2E2 \ :\ 2=RS423 output 900-9BF 2D1 2DA 2E3 \ :\ 3=printer 880-8BF 2D2 2DB 2E4 \ :\ 4=sound0 840-84F 2D3 2DC 2E5 \ :\ 5=sound1 850-85F 2D4 2DD 2E6 \ :\ 6=sound2 860-86F 2D5 2DE 2E7 \ :\ 7=sound3 870-87F 2D6 2DF 2E8 \ :\ 8=speech 8C0-8FF 2D7 2E0 2E9 LDA LE43E,X :\ get buffer base address lo STA &FA :\ store it LDA LE435,X :\ get buffer base address hi STA &FB :\ store it RTS :\ exit .LE45B \************************************************************************* \* * \* OSBYTE 152 Examine Buffer status * \* * \************************************************************************* \on entry X = buffer number \on exit FA/B points to buffer start Y is offset to next character \if buffer is empty C=1, Y is preserved else C=0 BIT LD9B7 :\ set V and BVS LE461 :\ jump to E461 .LE460 \************************************************************************* \* * \* OSBYTE 145 Get byte from Buffer * \* * \************************************************************************* \on entry X = buffer number \ ON EXIT Y is character extracted \if buffer is empty C=1, else C=0 CLV :\ clear V .LE461 JMP (&022C) :\ Jump via REMV \************************************************************************* \* * \* REMV buffer remove vector default entry point * \* * \************************************************************************* \on entry X = buffer number \on exit if buffer is empty C=1, Y is preserved else C=0 PHP :\ push flags SEI :\ bar interrupts LDA &02D8,X :\ get output pointer for buffer X CMP &02E1,X :\ compare to input pointer BEQ LE4E0 :\ if equal buffer is empty so E4E0 to exit TAY :\ else A=Y JSR LE450 :\ and get buffer pointer into FA/B LDA (&FA),Y :\ read byte from buffer BVS LE491 :\ if V is set (on input) exit with CARRY clear :\ Osbyte 152 has been done PHA :\ else must be osbyte 145 so save byte INY :\ increment Y TYA :\ A=Y BNE LE47E :\ if end of buffer not reached <>0 E47E LDA LE447,X :\ get pointer start from offset table .LE47E STA &02D8,X :\ set buffer output pointer CPX #&02 :\ if buffer is input (0 or 1) BCC LE48F :\ then E48F CMP &02E1,X :\ else for output buffers compare with buffer start BNE LE48F :\ if not the same buffer is not empty so E48F LDY #&00 :\ buffer is empty so Y=0 JSR LE494 :\ and enter EVENT routine to signal EVENT 0 buffer .LE48F :\ becoming empty PLA :\ get back byte from buffer TAY :\ put it in Y .LE491 PLP :\ get back flags CLC :\ clear carry to indicate success RTS :\ and exit .LE494 \************************************************************************** \************************************************************************** \** ** \** CAUSE AN EVENT ** \** ** \************************************************************************** \************************************************************************** \on entry Y=event number \A and X may be significant Y=A, A=event no. when event generated @E4A1 \on exit carry clear indicates action has been taken else carry set PHP :\ push flags SEI :\ bar interrupts PHA :\ push A STA &FA :\ &FA=A LDA &02BF,Y :\ get enable event flag BEQ LE4DF :\ if 0 event is not enabled so exit TYA :\ else A=Y LDY &FA :\ Y=A JSR LF0A5 :\ vector through &220 .LE4A4 PLA :\ get back A PLP :\ get back flags CLC :\ clear carry for success RTS :\ and exit .LE4A8 \********* check event 2 character entering buffer *********************** TYA :\ A=Y LDY #&02 :\ Y=2 JSR LE494 :\ check event TAY :\ Y=A .LE4AF \************************************************************************* \* * \* OSBYTE 138 Put byte into Buffer * \* * \************************************************************************* \on entry X is buffer number, Y is character to be written TYA :\ A=Y .LE4B0 JMP (&022A) :\ jump to INSBV \************************************************************************* \* * \* INSBV insert character in buffer vector default entry point * \* * \************************************************************************* \on entry X is buffer number, A is character to be written PHP :\ save flags SEI :\ bar interrupts PHA :\ save A LDY &02E1,X :\ get buffer input pointer INY :\ increment Y BNE LE4BF :\ if Y=0 then buffer is full else E4BF LDY LE447,X :\ get default buffer start .LE4BF TYA :\ put it in A CMP &02D8,X :\ compare it with input pointer BEQ LE4D4 :\ if equal buffer is full so E4D4 LDY &02E1,X :\ else get buffer end in Y STA &02E1,X :\ and set it from A JSR LE450 :\ and point &FA/B at it PLA :\ get back byte STA (&FA),Y :\ store it in buffer PLP :\ pull flags CLC :\ clear carry for success RTS :\ and exit .LE4D4 PLA :\ get back byte CPX #&02 :\ if we are working on input buffer BCS LE4E0 :\ then E4E0 LDY #&01 :\ else Y=1 JSR LE494 :\ to service input buffer full event PHA :\ push A .LE4DF \***** return with carry set ********************************************* PLA :\ restore A .LE4E0 PLP :\ restore flags SEC :\ set carry RTS :\ and exit .LE4E3 \***************** CODE MODIFIER ROUTINE ********************************* \* CHECK FOR ALPHA CHARACTER * \************************************************************************* :\ ENTRY character in A :\ exit with carry set if non-Alpha character PHA :\ Save A AND #&DF :\ convert lower to upper case CMP #&41 :\ is it 'A' or greater ?? BCC LE4EE :\ if not exit routine with carry set CMP #&5B :\ is it less than 'Z' BCC LE4EF :\ if so exit with carry clear .LE4EE SEC :\ else clear carry .LE4EF PLA :\ get back original value of A RTS :\ and Return .LE4F1 \******* INSERT byte in Keyboard buffer ********************************* LDX #&00 :\ X=0 to indicate keyboard buffer .LE4F3 \************************************************************************* \* * \* OSBYTE 153 Put byte in input Buffer checking for ESCAPE * \* * \************************************************************************* \on entry X = buffer number (either 0 or 1) \X=1 is RS423 input \X=0 is Keyboard \Y is character to be written TXA :\ A=buffer number AND &0245 :\ and with RS423 mode (0 treat as keyboard :\ 1 ignore Escapes no events no soft keys) BNE LE4AF :\ so if RS423 buffer AND RS423 in normal mode (1) E4AF TYA :\ else Y=A character to write EOR &026C :\ compare with current escape ASCII code (0=match) ORA &0275 :\ or with current ESCAPE status (0=ESC, 1=ASCII) BNE LE4A8 :\ if ASCII or no match E4A8 to enter byte in buffer LDA &0258 :\ else get ESCAPE/BREAK action byte ROR A :\ Rotate to get ESCAPE bit into carry TYA :\ get character back in A BCS LE513 :\ and if escape disabled exit with carry clear LDY #&06 :\ else signal EVENT 6 Escape pressed JSR LE494 :\ BCC LE513 :\ if event handles ESCAPE then exit with carry clear JSR LE674 :\ else set ESCAPE flag .LE513 CLC :\ clear carry RTS :\ and exit .LE515 \******** get a byte from keyboard buffer and interpret as necessary ***** \on entry A=cursor editing status 1=return &87-&8B, \2= use cursor keys as soft keys 11-15 \this area not reached if cursor editing is normal ROR A :\ get bit 1 into carry PLA :\ get back A BCS LE592 :\ if carry is set return .LE519 :\ else cursor keys are 'soft' TYA :\ A=Y get back original key code (&80-&FF) PHA :\ PUSH A LSR A :\ get high nybble into lo LSR A :\ LSR A :\ LSR A :\ A=8-&F EOR #&04 :\ and invert bit 2 :\ &8 becomes &C :\ &9 becomes &D :\ &A becomes &E :\ &B becomes &F :\ &C becomes &8 :\ &D becomes &9 :\ &E becomes &A :\ &F becomes &B TAY :\ Y=A = 8-F LDA &0265,Y :\ read 026D to 0274 code interpretation status :\ 0=ignore key, 1=expand as 'soft' key :\ 2-&FF add this to base for ASCII code :\ note that provision is made for keypad operation :\ as codes &C0-&FF cannot be generated from keyboard :\ but are recognised by OS :\ CMP #&01 :\ is it 01 BEQ LE594 :\ if so expand as 'soft' key via E594 PLA :\ else get back original byte BCC LE539 :\ if above CMP generated Carry then code 0 must have :\ been returned so E539 to ignore AND #&0F :\ else add ASCII to BASE key number so clear hi nybble CLC :\ clear carry ADC &0265,Y :\ add ASCII base CLC :\ clear carry RTS :\ and exit .LE534 :\ \*********** ERROR MADE IN USING EDIT FACILITY *************************** JSR LE86F :\ produce bell PLA :\ get back A, buffer number TAX :\ X=buffer number .LE539 \********get byte from buffer ******************************************** JSR LE460 :\ get byte from buffer X BCS LE593 :\ if buffer empty E593 to exit PHA :\ else Push byte CPX #&01 :\ and if RS423 input buffer is not the one BNE LE549 :\ then E549 JSR LE173 :\ else oswrch LDX #&01 :\ X=1 (RS423 input buffer) SEC :\ set carry .LE549 PLA :\ get back original byte BCC LE551 :\ if carry clear (INPUTE not RS423 input) E551 LDY &0245 :\ else Y=RS423 mode (0 treat as keyboard ) BNE LE592 :\ if not 0 ignore escapes etc. goto E592 .LE551 TAY :\ Y=A BPL LE592 :\ if code is less that &80 its simple so E592 AND #&0F :\ else clear high nybble CMP #&0B :\ if less than 11 then treat as special code BCC LE519 :\ or function key and goto E519 ADC #&7B :\ else add &7C (&7B +C) to convert codes B-F to 7-B PHA :\ Push A LDA &027D :\ get cursor editing status BNE LE515 :\ if not 0 (normal) E515 LDA &027C :\ else get character destination status \Bit 0 enables RS423 driver \BIT 1 disables VDU driver \Bit 2 disables printer driver \BIT 3 enables printer independent of CTRL B or CTRL C \Bit 4 disables spooled output \BIT 5 not used \Bit 6 disables printer driver unless VDU 1 precedes character \BIT 7 not used ROR A :\ get bit 1 into carry ROR A :\ PLA :\ BCS LE539 :\ if carry is set E539 screen disabled CMP #&87 :\ else is it COPY key BEQ LE5A6 :\ if so E5A6 TAY :\ else Y=A TXA :\ A=X PHA :\ Push X TYA :\ get back Y JSR LD8CE :\ execute edit action PLA :\ restore X TAX :\ .LE577 BIT &025F :\ check econet RDCH flag BPL LE581 :\ if not set goto E581 LDA #&06 :\ else Econet function 6 .LE57E JMP (&0224) :\ to the Econet vector .LE581 \********* get byte from key string ************************************** \on entry 0268 contains key length \and 02C9 key string pointer to next byte LDA &0268 :\ get length of keystring BEQ LE539 :\ if 0 E539 get a character from the buffer LDY &02C9 :\ get soft key expansion pointer LDA &0B01,Y :\ get character from string INC &02C9 :\ increment pointer DEC &0268 :\ decrement length .LE592 \************** exit with carry clear ************************************ CLC :\ .LE593 RTS :\ exit .LE594 :\ \*** expand soft key strings ********************************************* \Y=pointer to sring number PLA :\ restore original code AND #&0F :\ blank hi nybble to get key string number TAY :\ Y=A JSR LE3A8 :\ get string length in A STA &0268 :\ and store it LDA &0B00,Y :\ get start point STA &02C9 :\ and store it BNE LE577 :\ if not 0 then get byte via E577 and exit .LE5A6 \*********** deal with COPY key ****************************************** TXA :\ A=X PHA :\ Push A JSR LD905 :\ read a character from the screen TAY :\ Y=A BEQ LE534 :\ if not valid A=0 so BEEP PLA :\ else restore X TAX :\ TYA :\ and Y CLC :\ clear carry RTS :\ and exit .LE5B3 \************************************************************************* \* * \* OSBYTE LOOK UP TABLE * \* * \************************************************************************* AND (&E8,X) :\ OSBYTE 0 (&E821) DEY :\ OSBYTE 1 (&E988) SBC #&D3 :\ OSBYTE 2 (&E6D3) INC &97 :\ OSBYTE 3 (&E997) SBC #&97 :\ OSBYTE 4 (&E997) SBC #&76 :\ OSBYTE 5 (&E976) SBC #&88 :\ OSBYTE 6 (&E988) SBC #&8B :\ OSBYTE 7 (&E68B) INC &89 :\ OSBYTE 8 (&E689) INC &B0 :\ OSBYTE 9 (&E6B0) INC &B2 :\ OSBYTE 10 (&E6B2) INC &95 :\ OSBYTE 11 (&E995) SBC #&8C :\ OSBYTE 12 (&E98C) SBC #&F9 :\ OSBYTE 13 (&E6F9) INC &FA :\ OSBYTE 14 (&E6FA) INC &A8 :\ OSBYTE 15 (&F0A8) BEQ LE5DA :\ OSBYTE 16 (&E706) EQUB &E7 :\ OSBYTE 17 (&DE8C) STY LC8DE :\ :\ OSBYTE 18 (&E9C8) SBC #&B6 :\ OSBYTE 19 (&E9B6) .LE5DA SBC #&07 :\ OSBYTE 20 (&CD07) CMP LF0B4 :\ OSBYTE 21 (&F0B4) JMP (LD9E8) :\ OSBYTE 117 (&E86C) SBC #&75 :\ OSBYTE 119 (&E275) EQUB &E2 :\ OSBYTE 120 (&F045) EOR &F0 :\ EQUB &CF :\ OSBYTE 121 (&F0CF) BEQ LE5B7 :\ OSBYTE 122 (&F0CD) BEQ LE583 :\ OSBYTE 123 (&E197) SBC (&73,X) :\ OSBYTE 124 (&E673) INC &74 :\ OSBYTE 125 (&E674) INC &5C :\ OSBYTE 126 (&E65C) INC &35 :\ OSBYTE 127 (&E035) CPX #&4F :\ OSBYTE 128 (&E74F) EQUB &E7 :\ OSBYTE 129 (&E713) EQUB &13 :\ EQUB &E7 :\ OSBYTE 130 (&E729) AND #&E7 :\ STA &F0 :\ OSBYTE 131 (&F085) EQUB &23 :\ OSBYTE 132 (&D923) CMP LD926,Y :\ OSBYTE 133 (&D926) EQUB &47 :\ OSBYTE 134 (&D647) DEC &C2,X :\ OSBYTE 135 (&D7C2) EQUB &D7 :\ OSBYTE 136 (&E657) EQUB &57 :\ INC &7F :\ OSBYTE 137 (&E67F) INC &AF :\ OSBYTE 138 (&E4AF) CPX &34 :\ OSBYTE 139 (&E034) CPX #&35 :\ OSBYTE 140 (&F135) SBC (&35),Y :\ OSBYTE 141 (&F135) SBC (&E7),Y :\ OSBYTE 142 (&DBE7) EQUB &DB :\ OSBYTE 143 (&F168) PLA :\ SBC (&E3),Y :\ OSBYTE 144 (&EAE3) NOP :\ OSBYTE 145 (&E460) RTS :\ \ OSBYTE 146 (&FFAA) CPX &AA :\ EQUB &FF :\ OSBYTE 147 (&EAF4) EQUB &F4 :\ NOP :\ OSBYTE 148 (&FFAE) LDX LF9FF :\ :\ OSBYTE 149 (&EAF9) NOP :\ OSBYTE 150 (&FFB2) LDA (&FF) :\ INC &5BEA,X :\ OSBYTE 151 (&EAFE) :\ OSBYTE 152 (&E45B) CPX &F3 :\ OSBYTE 153 (&E4F3) CPX &FF :\ OSBYTE 154 (&E9FF) SBC #&10 :\ OSBYTE 155 (&EA10) NOP :\ OSBYTE 156 (&E17C) JMP (&A7E1,X) :\ \ OSBYTE 157 (&FFA7) EQUB &FF :\ OSBYTE 158 (&EE6D) ADC &7FEE :\ :\ OSBYTE 159 (&EE7F) INC LE9C0 :\ OSBYTE 160 (&E9C0) STZ &59E9 :\ OSBYTE 166+ \************************************************************************* \* * \* OSWORD LOOK UP TABLE * \* * \************************************************************************* INC &02 :\ OSWORD 0 (&E902) SBC #&D5 :\ OSWORD 1 (&E8D5) INX :\ OSWORD 2 (&E8E8) INX :\ INX :\ OSWORD 3 (&E8D1) CMP (&E8),Y :\ CPX &E8 :\ OSWORD 4 (&E8E4) EQUB &03 :\ OSWORD 5 (&E803) INX :\ OSWORD 6 (&E80B) EQUB &0B :\ INX :\ OSWORD 7 (&E82D) AND &AEE8 :\ :\ OSWORD 8 (&E8AE) INX :\ OSWORD 9 (&C735) AND &C7,X :\ EQUB &F3 :\ OSWORD 10 (&CBF3) EQUB &CB :\ OSWORD 11 (&C748) PHA :\ EQUB &C7 :\ OSWORD 12 (&C8E0) CPX #&C8 :\ DEC &A9D5 :\ OSWORD 13 (&D5CE) \************************************************************************* \* * \* OSBYTE 136 Execute Code via User Vector * \* * \* *CODE effectively * \* * \************************************************************************* BRK :\ A=0 \************************************************************************* \* * \* *LINE entry * \* * \************************************************************************* JMP (&0200) :\ Jump via USERV \************************************************************************* \* * \* OSBYTE 126 Acknowledge detection of ESCAPE condition * \* * \************************************************************************* \ X=0 LDX #&00 :\ BIT &FF :\ if bit 7 not set there is no ESCAPE condition BPL LE673 :\ so E673 LDA &0276 :\ else get ESCAPE Action, if this is 0 \;Clear ESCAPE \;close EXEC files \;purge all buffers \;reset VDU paging counter BNE LE671 :\ else do none of the above CLI :\ allow interrupts STA &0269 :\ number of lines printed since last halt in paged \;mode = 0 JSR LF68D :\ close any open EXEC files JSR LF0AA :\ clear all buffers .LE671 \X=&FF to indicate ESCAPE acknowledged LDX #&FF :\ \************************************************************************* \* * \* OSBYTE 124 Clear ESCAPE condition * \* * \************************************************************************* .LE673 \clear carry CLC :\ \************************************************************************* \* * \* OSBYTE 125 Set ESCAPE flag * \* * \************************************************************************* .LE674 \clear bit 7 of ESCAPE flag ROR &FF :\ BIT &027A :\ read bit 7 of Tube flag BMI LE67C :\ if set TUBE exists so E67C RTS :\ else RETURN :\ \ Jump to Tube entry point .LE67C JMP &0403 :\ \************************************************************************* \* * \* OSBYTE 137 Turn on Tape motor * \* * \************************************************************************* \ get serial ULA control setting LDA &0282 :\ TAY :\ Y=A ROL A :\ rotate left to get bit 7 into carry CPX #&01 :\ if X=1 then user wants motor on so CARRY set else \ :\ carry is cleared ROR A :\ put carry back in control RAM copy BVC LE6A7 :\ if bit 6 is clear then cassette is selected \ :\ so write to control register and RAM copy LDA #&38 :\ A=ASCII 8 \************************************************************************* \* * \* OSBYTE 08/07 set serial baud rates * \* * \************************************************************************* \ on entry X=baud rate \ A=8 transmit \ A=7 receive EOR #&3F :\ converts ASCII 8 to 7 binary and ASCII 7 to 8 binary STA &FA :\ store result LDY &0282 :\ get serial ULA control register setting CPX #&09 :\ is it 9 or more? BCS LE6AD :\ if so exit AND LE9AD,X :\ and with byte from look up table STA &FB :\ store it TYA :\ put Y in A ORA &FA :\ and or with Accumulator EOR &FA :\ zero the three bits set true ORA &FB :\ set up data read from look up table + bit 6 ORA #&40 :\ EOR &025D :\ write cassette/RS423 flag .LE6A7 \store serial ULA flag STA &0282 :\ STA LFE10 :\ and write to control register .LE6AD \put Y in A to save old contents TYA :\ .LE6AE \write new setting to X TAX :\ RTS :\ and return \OS SERIES VII \GEOFF COX \************************************************************************* \* * \* OSBYTE 9 Duration of first colour * \* * \************************************************************************* \on entry Y=0, X=new value \ Y is incremented to 1 INY :\ CLC :\ clear carry \************************************************************************* \* * \* OSBYTE 10 Duration of second colour * \* * \************************************************************************* \on entry Y=0 or 1 if from FX 9 call, X=new value LDA &0252,Y :\ get mark period count PHA :\ push it TXA :\ get new count STA &0252,Y :\ store it PLA :\ get back original value TAY :\ put it in Y LDA &0251 :\ get value of flash counter BNE LE6D1 :\ if not zero E6D1 STX &0251 :\ else restore old value LDA &0248 :\ get current video ULA control register setting PHP :\ push flags ROR A :\ rotate bit 0 into carry, carry into bit 7 PLP :\ get back flags ROL A :\ rotate back carry into bit 0 STA &0248 :\ store it in RAM copy STA LFE20 :\ and ULA control register .LE6D1 \then exit via OSBYTE 7/8 BVC LE6AD :\ \************************************************************************* \* * \* OSBYTE 2 select input stream * \* * \************************************************************************* \on input X contains stream number TXA :\ A=X AND #&01 :\ blank out bits 1 - 7 PHA :\ push A LDA &0250 :\ and get current ACIA control setting ROL A :\ Bit 7 into carry CPX #&01 :\ if X>=1 then ROR A :\ bit 7 of A=1 CMP &0250 :\ compare this with ACIA control setting PHP :\ push processor STA &0250 :\ put A into ACIA control setting STA LFE08 :\ and write to control register JSR LE173 :\ set up RS423 buffer PLP :\ get back P BEQ LE6F1 :\ if new setting different from old E6F1 else BIT LFE09 :\ set bit 6 and 7 .LE6F1 \get current input buffer number LDX &0241 :\ PLA :\ get back A STA &0241 :\ store it RTS :\ and return \************************************************************************* \* * \* OSBYTE 13 disable events * \* * \************************************************************************* \ :\ X contains event number 0-9 \ \ Y=0 A=0 TYA :\ \************************************************************************* \* * \* OSBYTE 14 enable events * \* * \************************************************************************* \X contains event number 0-9 CPX #&0A :\ if X>9 BCS LE6AE :\ goto E6AE for exit LDY &02BF,X :\ else get event enable flag STA &02BF,X :\ store new value in flag BVC LE6AD :\ and exit via E6AD \************************************************************************* \* * \* OSBYTE 16 Select A/D channel * \* * \************************************************************************* \X contains channel number or 0 if disable conversion BEQ LE70B :\ if X=0 then E70B JSR LDE8C :\ start conversion .LE70B \get current maximum ADC channel number LDA &024D :\ STX &024D :\ store new value TAX :\ put old value in X RTS :\ and exit \************************************************************************* \* * \* OSBYTE 129 Read key within time limit * \* * \************************************************************************* \X and Y contains either time limit in centi seconds Y=&7F max \ or Y=&FF and X=-ve INKEY value \ A=Y TYA :\ BMI LE721 :\ if Y=&FF the E721 CLI :\ else allow interrupts JSR LDEBB :\ and go to timed routine BCS LE71F :\ if carry set then E71F TAX :\ then X=A LDA #&00 :\ A=0 .LE71F \Y=A TAY :\ RTS :\ and return :\ :\ scan keyboard \ A=X .LE721 TXA :\ EOR #&7F :\ convert to keyboard input TAX :\ X=A JSR LF068 :\ then scan keyboard ROL A :\ put bit 7 into carry .LE729 \X=&FF LDX #&FF :\ LDY #&FF :\ Y=&FF BCS LE731 :\ if bit 7 of A was set goto E731 (RTS) INX :\ else X=0 INY :\ and Y=0 .LE731 \and exit RTS :\ \********** check occupancy of input or free space of output buffer ******* \ :\ X=buffer number \ :\ Buffer number Address Flag Out pointer In pointer \ :\ 0=Keyboard 3E0-3FF 2CF 2D8 2E1 \ :\ 1=RS423 Input A00-AFF 2D0 2D9 2E2 \ :\ 2=RS423 output 900-9BF 2D1 2DA 2E3 \ :\ 3=printer 880-8BF 2D2 2DB 2E4 \ :\ 4=sound0 840-84F 2D3 2DC 2E5 \ :\ 5=sound1 850-85F 2D4 2DD 2E6 \ :\ 6=sound2 860-86F 2D5 2DE 2E7 \ :\ 7=sound3 870-87F 2D6 2DF 2E8 \ :\ 8=speech 8C0-8FF 2D7 2E0 2E9 \ \ buffer number in A .LE732 TXA :\ EOR #&FF :\ invert it TAX :\ X=A CPX #&02 :\ is X>1 .LE738 \clear V flag CLV :\ BVC LE73E :\ and goto E73E count buffer .LE73B \set V BIT LD9B7 :\ .LE73E \CNPV defaults to E1D1 JMP (&022E) :\ \************* check RS423 input buffer ************************************ \ E741 SEC .LE741 SEC :\ LDX #&01 :\ X=1 to point to buffer JSR LE738 :\ and count it CPY #&01 :\ if the hi byte of the answer is 1 or more BCS LE74E :\ then Return CPX &025B :\ else compare with minimum buffer space .LE74E \and exit RTS :\ \************************************************************************* \* * \* OSBYTE 128 READ ADC CHANNEL * \* * \************************************************************************* \ON Entry, X=0 Exit Y contains number of last channel converted \ X=channel number X,Y contain 16 bit value read from channe \ X<0 Y=&FF X returns information about various buffers \ X=&FF (keyboard ) X=number of characters in buffer \ X=&FE (RS423 Input) X=number of characters in buffer \ X=&FD (RS423 output) X=number of empty spaces in buffer \ X=&FC (Printer) X=number of empty spaces in buffer \ X=&FB (sound 0) X=number of empty spaces in buffer \ X=&FA (sound 1) X=number of empty spaces in buffer \ X=&F9 (sound 2) X=number of empty spaces in buffer \ X=&F8 (sound 3) X=number of empty spaces in buffer \ X=&F7 (Speech ) X=number of empty spaces in buffer \ if X is -ve then E732 count spaces BMI LE732 :\ BEQ LE75F :\ if X=0 then E75F CPX #&05 :\ else check for Valid channel BCS LE729 :\ if not E729 set X & Y to 0 and exit LDY &02B9,X :\ get conversion values for channel of interest Hi & LDA &02B5,X :\ lo byte TAX :\ X=lo byte RTS :\ and exit \ read system VIA port B .LE75F LDA LFE40 :\ ROR A :\ move high nybble to low ROR A :\ ROR A :\ ROR A :\ EOR #&FF :\ and invert it AND #&03 :\ isolate the FIRE buttons LDY &02BE :\ get analogue system flag byte STX &02BE :\ store X here TAX :\ A=X bits 0 and 1 indicate fire buttons RTS :\ and return \************************************************************************** \************************************************************************** \** ** \** OSBYTE DEFAULT ENTRY POINT ** \** ** \** pointed to by default BYTEV ** \** ** \************************************************************************** \************************************************************************** \ save A PHA :\ PHP :\ save Processor flags SEI :\ disable interrupts STA &EF :\ store A,X,Y in zero page STX &F0 :\ STY &F1 :\ LDX #&07 :\ X=7 to signal osbyte is being attempted CMP #&75 :\ if A=0-116 BCC LE7C2 :\ then E7C2 CMP #&A1 :\ if A<161 BCC LE78E :\ then E78E CMP #&A6 :\ if A=161-165 BCC LE7C8 :\ then EC78 CLC :\ clear carry .LE78A \A=&A1 LDA #&A1 :\ ADC #&00 :\ \********* process osbyte calls 117 - 160 ***************************** .LE78E \set carry SEC :\ SBC #&5F :\ convert to &16 to &41 (22-65) .LE791 \double it (44-130) ASL A :\ SEC :\ set carry .LE793 \store Y STY &F1 :\ TAY :\ Y=A BIT &025E :\ read econet intercept flag BPL LE7A2 :\ if no econet intercept required E7A2 TXA :\ else A=X CLV :\ V=0 JSR LE57E :\ to JMP via ECONET vector BVS LE7BC :\ if return with V set E7BC .LE7A2 \get address from table LDA LE5B4,Y :\ STA &FB :\ store it as hi byte LDA LE5B3,Y :\ repeat for lo byte STA &FA :\ LDA &EF :\ restore A LDY &F1 :\ Y BCS LE7B6 :\ if carry is set E7B6 LDY #&00 :\ else LDA (&F0),Y :\ get value from address pointed to by &F0/1 (Y,X) .LE7B6 \set carry SEC :\ LDX &F0 :\ restore X JSR LF058 :\ call &FA/B .LE7BC \C=bit 0 ROR A :\ PLP :\ get back flags ROL A :\ bit 0=Carry PLA :\ get back A CLV :\ clear V RTS :\ and exit \*************** Process OSBYTE CALLS BELOW &75 ************************** \ Y=0 .LE7C2 LDY #&00 :\ CMP #&16 :\ if A<&16 BCC LE791 :\ goto E791 .LE7C8 \push flags PHP :\ PHP :\ push flags .LE7CA \pull flags PLA :\ PLA :\ pull flags JSR LF168 :\ offer paged ROMS service 7/8 unrecognised osbyte/word BNE LE7D6 :\ if roms don't recognise it then E7D6 LDX &F0 :\ else restore X JMP LE7BC :\ and exit \ else pull flags .LE7D6 PLP :\ PLA :\ and A BIT LD9B7 :\ set V and C RTS :\ and return \ read cassette critical flag bit 7 = busy .LE7DC LDA &EB :\ BMI LE812 :\ if busy then EB12 LDA #&08 :\ else A=8 to check current Catalogue status AND &E2 :\ by anding with CFS status flag BNE LE7EA :\ if not set (not in use) then E7EA RTS LDA #&88 :\ A=%10001000 AND &BB :\ AND with FS options (short msg bits) .LE7EA \ RETURN RTS :\ \************************************************************************** \************************************************************************** \** ** \** OSWORD DEFAULT ENTRY POINT ** \** ** \** pointed to by default WORDV ** \** ** \************************************************************************** \************************************************************************** \ Push A PHA :\ PHP :\ Push flags SEI :\ disable interrupts STA &EF :\ store A,X,Y STX &F0 :\ STY &F1 :\ LDX #&08 :\ X=8 CMP #&E0 :\ if A=>224 BCS LE78A :\ then E78A with carry set CMP #&0E :\ else if A=>14 BCS LE7C8 :\ else E7C8 with carry set pass to ROMS & exit ADC #&44 :\ add to form pointer to table ASL A :\ double it BCC LE793 :\ goto E793 ALWAYS!! (carry clear E7F8) :\ this reads bytes from table and enters routine \************************************************************************* \* * \* OSWORD 05 ENTRY POINT * \* * \* read a byte from I/O memory * \* * \************************************************************************* \block of 4 bytes set at address pointed to by 00F0/1 (Y,X) \XY +0 ADDRESS of byte \ +4 on exit byte read JSR LE815 :\ set up address of data block LDA (&F9,X) :\ get byte STA (&F0),Y :\ store it RTS :\ exit \************************************************************************* \* * \* OSWORD 06 ENTRY POINT * \* * \* write a byte to I/O memory * \* * \************************************************************************* \block of 5 bytes set at address pointed to by 00F0/1 (Y,X) \XY +0 ADDRESS of byte \ +4 byte to be written \ set up address JSR LE815 :\ LDA (&F0),Y :\ get byte STA (&F9,X) :\ store it .LE812 \a=0 LDA #&00 :\ RTS :\ exit \******************** set up data block ********************************* \ &FA=A .LE815 STA &FA :\ INY :\ Y=1 LDA (&F0),Y :\ get byte from block STA &FB :\ store it LDY #&04 :\ Y=4 .LE81E \X=1 LDX #&01 :\ RTS :\ and exit \************************************************************************* \* * \* OSBYTE 00 ENTRY POINT * \* * \* read OS version number * \* * \************************************************************************* \ if A <> 0 then exit else print error BNE LE81E :\ BRK :\ EQUB &F7 :\ error number EQUB &4F :\ error message EQUB &53 :\ E82C BRK JSR &2E31 :\ AND (&30) :\ BRK :\ \************************************************************************* \************************************************************************* \** ** \** SOUND SYSTEM ** \** ** \************************************************************************* \************************************************************************* \------------------------------------------------------------------------- \| | \| OSWORD 07 - Make a sound | \| | \------------------------------------------------------------------------- \ On entry, control block pointed to by &F0/1 \ Y=0 on entry \ XY +0 Channel - &hsfc for Hold, Sync, Flush, Channel \ 2 Amplitude/Envelope \ 4 Pitch \ 6 Duration INY :\ E82D INY LDA (&F0),Y :\ Get channel high byte byte CMP #&FF :\ E830 CMP #&FF BEQ LE88D :\ Channel &FFxx, speech command CMP #&20 :\ Is channel>=&20 ? LDX #&08 :\ Prepare X=8 for unrecognised OSWORD call BCS LE7CA :\ Pass to sideways ROMs for channel &2000+ DEY :\ Point back to channel low byte JSR LE8C9 :\ Get Channel 0-3, and Cy if >=&10 for Flush ORA #&04 :\ Convert to buffer number 4-7 TAX :\ E840 TAX BCC LE848 :\ If not Flush, skip past JSR LE1AE :\ Flush buffer LDY #&01 :\ Point back to channel high byte .LE848 \ Get Sync 0-3, and Cy if >=&10 for Hold JSR LE8C9 :\ STA &FA :\ Save Sync in &FA PHP :\ Stack flags LDY #&06 :\ E84E LDY #&06 LDA (&F0),Y :\ Get Duration byte PHA :\ and stack it LDY #&04 :\ E853 LDY #&04 LDA (&F0),Y :\ Get pitch byte PHA :\ and stack it LDY #&02 :\ LDA (&F0),Y :\ Get amplitude/envelope byte ROL A :\ Move Hold into bit 0 SEC :\ set carry SBC #&02 :\ subract 2 ASL A :\ multiply by 4 ASL A :\ ORA &FA :\ add S byte (0-3) \ :\ At this point, \ :\ b7, 0=envelope, 1=volume \ :\ b6-3, envelope-1 or volume+15 \ :\ b2, Hold \ :\ b1-0, Sync JSR LE1F8 :\ Insert into buffer BCC LE887 :\ Buffer not full, jump to insert the rest .LE869 \ Drop stacked pitch PLA :\ PLA :\ Drop stacked duration PLP :\ Restore flags :\ And exit \------------------------------------------------------------------------- \| | \| OSBYTE 117 - Read VDU status | \| | \------------------------------------------------------------------------- LDX &D0 :\ get VDU status byte in X RTS :\ and return \************* set up sound data for Bell ******************************** \ push P .LE86F PHP :\ SEI :\ bar interrupts LDA &0263 :\ get bell channel number in A AND #&07 :\ (bits 0-3 only set) ORA #&04 :\ set bit 2 TAX :\ X=A = bell channel number +4=buffer number LDA &0264 :\ get bell amplitude/envelope number JSR LE4B0 :\ store it in buffer pointed to by X LDA &0266 :\ get bell duration PHA :\ save it LDA &0265 :\ get bell frequency PHA :\ save it \ Insert sound pitch and duration into sound buffer \ .LE887 \ Set carry SEC :\ ROR &0800,X :\ Set bit 7 of channel flags to indicate it's active BMI LE8A4 :\ Jump forward to insert pitch and duration \------------------------------------------------------------------------- \| | \| SOUND &FFxx - Speech System | \| | \------------------------------------------------------------------------- \ On entry, control block pointed to by &F0/1 \ Y=1 on entry \ XY +0 Channel - &FFxx - xx=Speech command \ 2 Word number/Address \ 4 Ignored \ 6 Ignored .LE88D \ Save flags PHP :\ INY :\ Y=2 LDA (&F0),Y :\ Get word number low byte PHA :\ and stack it INY :\ Y=3 LDA (&F0),Y :\ Get word number high byte PHA :\ and stack it LDY #&00 :\ Y=0 LDA (&F0),Y :\ Get speech command LDX #&08 :\ X=8 for Speech buffer JSR LE1F8 :\ Insert speech command into speech buffer BCS LE869 :\ Buffer full, drop stack and abandon ROR &02D7 :\ Clear bit 7 of speech buffer busy flag \ Insert two bytes into buffer \ .LE8A4 \ Get word number high byte or pitch back PLA :\ JSR LE4B0 :\ Insert into speech buffer PLA :\ Get word number low byte or duration back JSR LE4B0 :\ Insert into speech buffer PLP :\ Restore flags RTS :\ and return \************************************************************************* \* * \* OSWORD 08 - Define Envelope * \* * \************************************************************************* \ On entry, control block pointed to by &F0/1 \ Y=0 on entry \ A=envelope number from (&F0),0 \XY +0 Envelope number, also in A \ 1 bits 0-6 length of each step in centi-secsonds bit 7=0 auto repeat \ 2 change of Pitch per step (-128-+127) in section 1 \ 3 change of Pitch per step (-128-+127) in section 2 \ 4 change of Pitch per step (-128-+127) in section 3 \ 5 number of steps in section 1 (0-255) \ 6 number of steps in section 2 (0-255) \ 7 number of steps in section 3 (0-255) \ 8 change of amplitude per step during attack phase (-127 to +127) \ 9 change of amplitude per step during decay phase (-127 to +127) \ 10 change of amplitude per step during sustain phase (-127 to +127) \ 11 change of amplitude per step during release phase (-127 to +127) \ 12 target level at end of attack phase (0-126) \ 13 target level at end of decay phase (0-126) \ set up appropriate displacement to storage area SBC #&01 :\ ASL A :\ A=(A-1)*16 or 15 ASL A :\ ASL A :\ ASL A :\ ORA #&0F :\ TAX :\ X=A LDA #&00 :\ A=0 LDY #&10 :\ Y=&10 .LE8BB \is Y>=14?? CPY #&0E :\ BCS LE8C1 :\ yes then E8C1 LDA (&F0),Y :\ else get byte from parameter block .LE8C1 \and store it in appropriate area STA &08C0,X :\ DEX :\ decrement X DEY :\ Decrement Y BNE LE8BB :\ if not 0 then do it again RTS :\ else exit :\ note that envelope number is NOT transferred \ \ get byte .LE8C9 LDA (&F0),Y :\ CMP #&10 :\ is it greater than 15, if so set carry AND #&03 :\ and 3 to clear bits 2-7 INY :\ increment Y RTS :\ and exit \************************************************************************* \* * \* OSWORD 03 ENTRY POINT * \* * \* read interval timer * \* * \************************************************************************* \F0/1 points to block to store data \ X=&F displacement from clock to timer LDX #&0F :\ BNE LE8D8 :\ jump to E8D8 \************************************************************************* \* * \* OSWORD 01 ENTRY POINT * \* * \* read system clock * \* * \************************************************************************* \F0/1 points to block to store data LDX &0283 :\ X=current system clock store pointer .LE8D8 \Y=4 LDY #&04 :\ .LE8DA \read byte LDA &028D,X :\ STA (&F0),Y :\ store it in parameter block INX :\ X=x+1 DEY :\ Y=Y-1 BPL LE8DA :\ if Y>0 then do it again .LE8E3 \else exit RTS :\ \************************************************************************* \* * \* OSWORD 04 ENTRY POINT * \* * \* write interval timer * \* * \************************************************************************* \F0/1 points to block to store data \ offset between clock and timer LDA #&0F :\ BNE LE8EE :\ jump to E8EE ALWAYS!! \************************************************************************* \* * \* OSWORD 02 ENTRY POINT * \* * \* write system clock * \* * \************************************************************************* \F0/1 points to block to store data LDA &0283 :\ get current clock store pointer EOR #&0F :\ and invert to get inactive timer CLC :\ clear carry .LE8EE \store A PHA :\ TAX :\ X=A LDY #&04 :\ Y=4 .LE8F2 \and transfer all 5 bytes LDA (&F0),Y :\ STA &028D,X :\ to the clock or timer INX :\ DEY :\ BPL LE8F2 :\ if Y>0 then E8F2 PLA :\ get back stack BCS LE8E3 :\ if set (write to timer) E8E3 exit STA &0283 :\ write back current clock store RTS :\ and exit \************************************************************************* \* * \* OSWORD 00 ENTRY POINT * \* * \* read line from current input to memory * \* * \************************************************************************* \F0/1 points to parameter block \ +0/1 Buffer address for input \ +2 Maximum line length \ +3 minimum acceptable ASCII value \ +4 maximum acceptable ASCII value \ Y=4 LDY #&04 :\ .LE904 \transfer bytes 4,3,2 to 2B3-2B5 LDA (&F0),Y :\ STA &02B1,Y :\ DEY :\ decrement Y CPY #&02 :\ until Y=1 BCS LE904 :\ LDA (&F0),Y :\ get address of input buffer STA &E9 :\ store it in &E9 as temporary buffer DEY :\ decrement Y STY &0269 :\ Y=0 store in print line counter for paged mode LDA (&F0),Y :\ get lo byte of address STA &E8 :\ and store in &E8 CLI :\ allow interrupts BCC LE924 :\ Jump to E924 .LE91D \A=7 LDA #&07 :\ .LE91F \decrement Y DEY :\ .LE920 \increment Y INY :\ .LE921 \and call OSWRCH JSR OSWRCH :\ .LE924 \else read character from input stream JSR OSRDCH :\ BCS LE972 :\ if carry set then illegal character or other error :\ exit via E972 TAX :\ X=A LDA &027C :\ A=&27C get character destination status ROR A :\ put VDU driver bit in carry ROR A :\ if this is 1 VDU driver is disabled TXA :\ X=A BCS LE937 :\ if Carry set E937 LDX &026A :\ get number of items in VDU queque BNE LE921 :\ if not 0 output character and loop round again .LE937 \if character is not delete CMP #&7F :\ BNE LE942 :\ goto E942 CPY #&00 :\ else is Y=0 BEQ LE924 :\ and goto E924 DEY :\ decrement Y BCS LE921 :\ and if carry set E921 to output it .LE942 \is it delete line &21 CMP #&15 :\ BNE LE953 :\ if not E953 TYA :\ else Y=A, if its 0 we are still reading first :\ character BEQ LE924 :\ so E924 LDA #&7F :\ else output DELETES .LE94B \until Y=0 JSR OSWRCH :\ DEY :\ BNE LE94B :\ BEQ LE924 :\ then read character again .LE953 \store character in designated buffer STA (&E8),Y :\ CMP #&0D :\ is it CR? BEQ LE96C :\ if so E96C CPY &02B3 :\ else check the line length BCS LE91D :\ if = or greater loop to ring bell CMP &02B4 :\ check minimum character BCC LE91F :\ if less than minimum backspace CMP &02B5 :\ check maximum character BEQ LE920 :\ if equal E920 BCC LE920 :\ or less E920 BCS LE91F :\ then JUMP E91F .LE96C \output CR/LF JSR OSNEWL :\ JSR LE57E :\ call Econet vector .LE972 \A=ESCAPE FLAG LDA &FF :\ ROL A :\ put bit 7 into carry RTS :\ and exit routine \************************************************************************* \* * \* OSBYTE 05 ENTRY POINT * \* * \* SELECT PRINTER TYPE * \* * \************************************************************************* \ allow interrupts briefly .LE976 CLI :\ SEI :\ bar interrupts BIT &FF :\ check if ESCAPE is pending BMI LE9AC :\ if it is E9AC BIT &02D2 :\ else check bit 7 buffer 3 (printer) BPL LE976 :\ if not empty bit 7=0 E976 JSR LE1A4 :\ check for user defined routine LDY #&00 :\ Y=0 STY &F1 :\ F1=0 \************************************************************************* \* * \* OSBYTE 01 ENTRY POINT * \* * \* READ/WRITE USER FLAG (&281) * \* * \* AND * \* * \* OSBYTE 06 ENTRY POINT * \* * \* SET PRINTER IGNORE CHARACTER * \* * \************************************************************************* \ A contains osbyte number ORA #&F0 :\ A=osbyte +&F0 BNE LE99A :\ JUMP to E99A \************************************************************************* \* * \* OSBYTE 0C ENTRY POINT * \* * \* SET KEYBOARD AUTOREPEAT RATE * \* * \************************************************************************* BNE LE995 :\ if &F0<>0 goto E995 LDX #&32 :\ if X=0 in original call then X=32 STX &0254 :\ to set keyboard autorepeat delay ram copy LDX #&08 :\ X=8 \************************************************************************* \* * \* OSBYTE 0B ENTRY POINT * \* * \* SET KEYBOARD AUTOREPEAT DELAY * \* * \************************************************************************* .LE995 \A=A+&D0 (carry set) ADC #&CF :\ \************************************************************************* \* * \* OSBYTE 03 ENTRY POINT * \* * \* SELECT OUTPUT STREAM * \* * \* AND * \* * \* * \* OSBYTE 04 ENTRY POINT * \* * \* ENABLE/DISABLE CURSOR EDITING * \* * \************************************************************************* CLC :\ c,ear carry ADC #&E9 :\ A=A+&E9 .LE99A \store X STX &F0 :\ \************************************************************************* \* * \* OSBYTE A6-FF ENTRY POINT * \* * \* READ/ WRITE SYSTEM VARIABLE OSBYTE NOT +&190 * \* * \************************************************************************* TAY :\ Y=A LDA &0190,Y :\ i.e. A=&190 +osbyte call! TAX :\ preserve this AND &F1 :\ new value = OLD value AND Y EOR X! EOR &F0 :\ STA &0190,Y :\ store it LDA &0191,Y :\ get value of next byte into A TAY :\ Y=A .LE9AC and exit RTS :\ \******* SERIAL BAUD RATE LOOK UP TABLE ************************************ \ % 01100100 75 .LE9AD STZ &7F :\ :\ % 01111111 150 EQUB &5B :\ % 01011011 300 ADC LF6C9 :\ % 01101101 1200 CMP (&E4) :\ % 11010010 9600 RTI :\ % 01000000 \************************************************************************* \* * \* OSBYTE &13 ENTRY POINT * \* * \* Wait for VSync * \* * \************************************************************************* LDA &0240 :\ read vertical sync counter .LE9B9 CLI :\ allow interrupts briefly SEI :\ bar interrupts CMP &0240 :\ has it changed? BEQ LE9B9 :\ no then E9B9 .LE9C0 \ falls through and reads VDU variable X \************************************************************************* \* * \* OSBYTE 160 ENTRY POINT * \* * \* READ VDU VARIABLE * \* * \************************************************************************* \X contains the variable number \0 =lefthand column in pixels current graphics window \2 =Bottom row in pixels current graphics window \4 =Right hand column in pixels current graphics window \6 =Top row in pixels current graphics window \8 =lefthand column in absolute characters current text window \9 =Bottom row in absolute characters current text window \10 =Right hand column in absolute characters current text window \11 =Top row in absolute characters current text window \12-15 current graphics origin in external coordinates \16-19 current graphics cursor in external coordina4es \20-23 old graphics cursor in internal coordinates \24 current text cursor in X and Y LDY &0301,X :\ get VDU variable hi LDA &0300,X :\ low TAX :\ X=low byte RTS :\ and exit .LE9C8 \************************************************************************* \* * \* OSBYTE 18 ENTRY POINT * \* * \* RESET SOFT KEYS * \* * \************************************************************************* LDA #&10 :\ set consistency flag STA &0284 :\ LDX #&00 :\ X=0 .LE9CF STA &0B00,X :\ and wipe clean INX :\ soft key buffer BNE LE9CF :\ until X=0 again STX &0284 :\ zero consistency flag RTS :\ and exit .LE9D9 \************************************************************************* \* * \* OSBYTE &76 (118) SET LEDs to Keyboard Status * \* * \************************************************************************* \ :\ osbyte entry with carry set \ :\ called from &CB0E, &CAE3, &DB8B PHP :\ PUSH P SEI :\ DISABLE INTERUPTS LDA #&40 :\ switch on CAPS and SHIFT lock lights JSR LE9EA :\ via subroutine BMI LE9E7 :\ if ESCAPE exists (M set) E9E7 CLC :\ else clear V and C CLV :\ before calling main keyboard routine to JSR LF068 :\ switch on lights as required .LE9E7 PLP :\ get back flags ROL A :\ and rotate carry into bit 0 RTS :\ Return to calling routine .LE9EA \ :\ \***************** Turn on keyboard lights and Test Escape flag ************ :\ called from &E1FE, &E9DD :\ BCC LE9F5 :\ if carry clear LDY #&07 :\ switch on shift lock light STY LFE40 :\ DEY :\ Y=6 STY LFE40 :\ switch on Caps lock light .LE9F5 BIT &FF :\ set minus flag if bit 7 of &00FF is set indicating RTS :\ that ESCAPE condition exists, then return .LE9F8 \ :\ \****************** Write A to SYSTEM VIA register B ************************* :\ called from &CB6D, &CB73 PHP :\ push flags SEI :\ disable interupts STA LFE40 :\ write register B from Accumulator PLP :\ get back flags RTS :\ and exit \************************************************************************* \* * \* OSBYTE 154 (&9A) SET VIDEO ULA * \* * \************************************************************************* TXA :\ osbyte entry! X transferred to A thence to .LEA00 \*******Set Video ULA control register **entry from VDU routines ************** \ :\ called from &CBA6, &DD37 PHP :\ save flags SEI :\ disable interupts STA &0248 :\ save RAM copy of new parameter STA LFE20 :\ write to control register LDA &0253 :\ read space count STA &0251 :\ set flash counter to this value PLP :\ get back status RTS :\ and return \************************************************************************* \* * \* OSBYTE &9B (155) write to palette register * \* * \************************************************************************* \entry X contains value to write TXA :\ A=X .LEA11 EOR #&07 :\ convert to palette format PHP :\ SEI :\ prevent interrupts STA &0249 :\ store as current palette setting STA LFE21 :\ store actual colour in register PLP :\ get back flags RTS :\ and exit .LEA1D \************************************************************************* \* GSINIT string initialisation * \* F2/3 points to string offset by Y * \* * \* ON EXIT * \* Z flag set indicates null string, * \* Y points to first non blank character * \* A contains first non blank character * \************************************************************************* CLC :\ clear carry .LEA1E ROR &E4 :\ Rotate moves carry to &E4 JSR LE03A :\ get character from text INY :\ increment Y to point at next character CMP #&22 :\ check to see if its '"' BEQ LEA2A :\ if so EA2A (carry set) DEY :\ decrement Y CLC :\ clear carry .LEA2A ROR &E4 :\ move bit 7 to bit 6 and put carry in bit 7 CMP #&0D :\ check to see if its CR to set Z RTS :\ and return .LEA2F \************************************************************************* \* GSREAD string read routine * \* F2/3 points to string offset by Y * \* * \************************************************************************* \ :\ LDA #&00 :\ A=0 .LEA31 STA &E5 :\ store A LDA (&F2),Y :\ read first character CMP #&0D :\ is it CR BNE LEA3F :\ if not goto EA3F BIT &E4 :\ if bit 7=1 no 2nd '"' found BMI LEA8F :\ goto EA8F BPL LEA5A :\ if not EA5A .LEA3F CMP #&20 :\ is less than a space? BCC LEA8F :\ goto EA8F BNE LEA4B :\ if its not a space EA4B BIT &E4 :\ is bit 7 of &E4 =1 BMI LEA89 :\ if so goto EA89 BVC LEA5A :\ if bit 6 = 0 EA5A .LEA4B CMP #&22 :\ is it '"' BNE LEA5F :\ if not EA5F BIT &E4 :\ if so and Bit 7 of &E4 =0 (no previous ") BPL LEA89 :\ then EA89 INY :\ else point at next character LDA (&F2),Y :\ get it CMP #&22 :\ is it '"' BEQ LEA89 :\ if so then EA89 .LEA5A JSR LE03A :\ read a byte from text SEC :\ and return with RTS :\ carry set .LEA5F :\ CMP #&7C :\ is it '|' BNE LEA89 :\ if not EA89 INY :\ if so increase Y to point to next character LDA (&F2),Y :\ get it CMP #&7C :\ and compare it with '|' again BEQ LEA89 :\ if its '|' then EA89 CMP #&22 :\ else is it '"' BEQ LEA89 :\ if so then EA89 CMP #&21 :\ is it ! BNE LEA77 :\ if not then EA77 INY :\ increment Y again LDA #&80 :\ set bit 7 BNE LEA31 :\ loop back to EA31 to set bit 7 in next CHR .LEA77 CMP #&20 :\ is it a space BCC LEA8F :\ if less than EA8F Bad String Error CMP #&3F :\ is it '?' BEQ LEA87 :\ if so EA87 JSR LEABF :\ else modify code as if CTRL had been pressed BIT LD9B7 :\ if bit 6 set BVS LEA8A :\ then EA8A .LEA87 LDA #&7F :\ else set bits 0 to 6 in A .LEA89 CLV :\ clear V .LEA8A INY :\ increment Y ORA &E5 :\ CLC :\ clear carry RTS :\ Return .LEA8F :\ BRK :\ SBC &6142,X :\ error number STZ &20 :\ message EQUB &73 :\ STZ &72,X :\ ADC #&6E :\ EQUB &67 :\ BRK :\ \************ Modify code as if SHIFT pressed ***************************** .LEA9C \if A='0' skip routine CMP #&30 :\ BEQ LEABE :\ CMP #&40 :\ if A='@' skip routine BEQ LEABE :\ BCC LEAB8 :\ if A<'@' then EAB8 CMP #&7F :\ else is it DELETE BEQ LEABE :\ if so skip routine BCS LEABC :\ if greater than &7F then toggle bit 4 .LEAAC \reverse bits 4 and 5 EOR #&30 :\ CMP #&6F :\ is it &6F (previously ' _' (&5F)) BEQ LEAB6 :\ goto EAB6 CMP #&50 :\ is it &50 (previously '`' (&60)) BNE LEAB8 :\ if not EAB8 .LEAB6 \else continue to convert ` _ EOR #&1F :\ .LEAB8 \compare &21 '!' CMP #&21 :\ BCC LEABE :\ if less than return .LEABC \else finish conversion by toggling bit 4 EOR #&10 :\ .LEABE \exit RTS :\ \ :\ \ :\ ASCII codes &00 &20 no change \ :\ 21-3F have bit 4 reverses (31-3F) \ :\ 41-5E A-Z have bit 5 reversed a-z \ :\ 5F & 60 are reversed \ :\ 61-7E bit 5 reversed a-z becomes A-Z \ :\ DELETE unchanged \ :\ &80+ has bit 4 changed \************** Implement CTRL codes ************************************* \ is it DEL .LEABF CMP #&7F :\ BEQ LEAD1 :\ if so ignore routine BCS LEAAC :\ if greater than &7F go to EAAC CMP #&60 :\ if A<>'`' BNE LEACB :\ goto EACB LDA #&5F :\ if A=&60, A=&5F .LEACB \if A<&40 CMP #&40 :\ BCC LEAD1 :\ goto EAD1 and return unchanged AND #&1F :\ else zero bits 5 to 7 .LEAD1 \return RTS :\ :\ \ EAD2 DB '/!BOOT',&0D EQUB &2F :\ \OS SERIES 8 \GEOFF COX \************************************************************************* \* * \* OSBYTE &F7 (247) INTERCEPT BREAK * \* * \************************************************************************* AND (&42,X) :\ get BREAK vector code EQUB &4F :\ EQUB &4F :\ EQUB &54 :\ ORA &87AD :\ EQUB &02 :\ produces 0 if JMP not in &287 EOR #&4C :\ BNE LEAF3 :\ if not goto EAF3 JMP &0287 :\ else jump to user BREAK code \************************************************************************* \* * \* OSBYTE &90 (144) *TV * \* * \************************************************************************* \ :\ X=display delay \ :\ Y=interlace flag \ \ VDU vertical adjustment LDA &0290 :\ STX &0290 :\ store new value TAX :\ put old value in X TYA :\ put interlace flag in A AND #&01 :\ maximum value =1 LDY &0291 :\ get old value into Y STA &0291 :\ put new value into A .LEAF3 \and Exit RTS :\ \************************************************************************* \* * \* OSBYTE &93 (147) WRITE TO FRED * \* * \************************************************************************* :\ X is offset within page :\ Y is byte to write TYA :\ STA LFC00,X :\ RTS :\ \************************************************************************* \* * \* OSBYTE &95 (149) WRITE TO JIM * \* * \************************************************************************* :\ X is offset within page :\ Y is byte to write :\ TYA :\ STA LFD00,X :\ RTS :\ \************************************************************************* \* * \* OSBYTE &97 (151) WRITE TO SHEILA * \* * \************************************************************************* :\ X is offset within page :\ Y is byte to write :\ TYA :\ STA LFE00,X :\ RTS :\ \****************** Silence a sound channel ******************************* :\ X=channel number \ mark end of release phase .LEB03 LDA #&04 :\ STA &0808,X :\ to channel X LDA #&C0 :\ load code for zero volume \****** if sound not disabled set sound generator volume ****************** .LEB0A \store A to give basic sound level of Zero STA &0804,X :\ LDY &0262 :\ get sound output/enable flag BEQ LEB14 :\ if sound enabled goto EB14 LDA #&C0 :\ else load zero sound code .LEB14 \set carry SEC :\ SBC #&40 :\ subtract &40 LSR A :\ divide by 8 LSR A :\ to get into bits 0 - 3 LSR A :\ EOR #&0F :\ invert bits 0-3 ORA LEB3C,X :\ get channel number into top nybble ORA #&10 :\ .LEB21 PHP :\ .LEB22 \disable interrupts SEI :\ LDY #&FF :\ System VIA port A all outputs STY LFE43 :\ set STA LFE4F :\ output A on port A INY :\ Y=0 STY LFE40 :\ enable sound chip LDY #&02 :\ set and .LEB31 \execute short delay DEY :\ BNE LEB31 :\ LDY #&08 :\ then disable sound chip again STY LFE40 :\ LDY #&04 :\ set delay .LEB3B \and loop delay DEY :\ .LEB3C BNE LEB3B :\ PLP :\ get back flags RTS :\ and exit \******* Sound parameters look up table ********************************** \ EB40 DB &E0,&C0,&A0,&80 CPX #&C0 :\ LDY #&80 :\ just to allow relative branches in early part .LEB44 JMP LEC59 :\ \ :\ of sound interrupt routine \************************************************************************* \* * \* PROCESS SOUND INTERRUPT * \* * \************************************************************************* .LEB47 LDA #&00 :\ STA &083B :\ zero number of channels on hold for sync LDA &0838 :\ get number of channels required for sync BNE LEB57 :\ if this <>0 then EB57 INC &083B :\ else number of chanels on hold for sync =1 DEC &0838 :\ number of channels required for sync =255 .LEB57 \set loop counter LDX #&08 :\ .LEB59 \loop DEX :\ LDA &0800,X :\ get value of &800 +offset (sound queue occupancy) BEQ LEB44 :\ if 0 goto EC59 no sound this channel LDA &02CF,X :\ else get buffer busy flag BMI LEB69 :\ if negative (buffer empty) goto EB69 LDA &0818,X :\ else if duration count not zer0 BNE LEB6C :\ goto EB6C .LEB69 \check and pick up new sound if required JSR LEC6B :\ .LEB6C \if duration count 0 LDA &0818,X :\ BEQ LEB84 :\ goto EB84 CMP #&FF :\ else if it is &FF (infinite duration) BEQ LEB87 :\ go onto EB87 DEC &081C,X :\ decrement 10 mS count BNE LEB87 :\ and if 0 LDA #&05 :\ reset to 5 STA &081C,X :\ to give 50 mSec delay DEC &0818,X :\ and decrement main counter BNE LEB87 :\ if not zero then EB87 .LEB84 \else check and get nw sound JSR LEC6B :\ .LEB87 \if step progress counter is 0 no envelope involved LDA &0824,X :\ BEQ LEB91 :\ so jump to EB91 DEC &0824,X :\ else decrement it BNE LEB44 :\ and if not zero go on to EC59 .LEB91 \get envelope data offset from (8C0) LDY &0820,X :\ CPY #&FF :\ if 255 no envelope set so BEQ LEB44 :\ goto EC59 LDA &08C0,Y :\ else get get step length .LEB9B \zero repeat bit AND #&7F :\ STA &0824,X :\ and store it LDA &0808,X :\ get phase counter CMP #&04 :\ if release phase completed BEQ LEC07 :\ goto EC07 LDA &0808,X :\ else start new step by getting phase CLC :\ ADC &0820,X :\ add it to interval multiplier TAY :\ transfer to Y LDA &08CB,Y :\ and get target value base for envelope SEC :\ SBC #&3F :\ STA &083A :\ store modified number as current target amplitude LDA &08C7,Y :\ get byte from envelope store STA &0839 :\ store as current amplitude step LDA &0804,X :\ get base volumelevel PHA :\ save it CLC :\ clear carry ADC &0839 :\ add to current amplitude step BVC LEBCF :\ if no overflow ROL A :\ double it Carry = bit 7 LDA #&3F :\ if bit =1 A=&3F BCS LEBCF :\ into &EBCF EOR #&FF :\ else toggle bits (A=&C0) \ :\ at this point the BASIC volume commands are converted \ :\ &C0 (0) to &38 (-15) 3 times, In fact last 3 bits \ :\ are ignored so &3F represents -15 .LEBCF \store in current volume STA &0804,X :\ ROL A :\ multiply by 2 EOR &0804,X :\ if bits 6 and 7 are equal BPL LEBE1 :\ goto &EBE1 LDA #&3F :\ if carry clear A=&3F (maximum) BCC LEBDE :\ or EOR #&FF :\ &C0 minimum .LEBDE \and this is stored in current volume STA &0804,X :\ .LEBE1 \decrement amplitude change per step DEC &0839 :\ LDA &0804,X :\ get volume again SEC :\ set carry SBC &083A :\ subtract target value EOR &0839 :\ negative value undicates correct trend BMI LEBF9 :\ so jump to next part LDA &083A :\ else enter new phase STA &0804,X :\ INC &0808,X :\ .LEBF9 \get the old volume level PLA :\ EOR &0804,X :\ and compare with the old AND #&F8 :\ BEQ LEC07 :\ if they are the same goto EC07 LDA &0804,X :\ else set new level JSR LEB0A :\ via EB0A .LEC07 \get absolute pitch value LDA &0810,X :\ CMP #&03 :\ if it =3 BEQ LEC59 :\ skip rest of loop as all sections are finished LDA &0814,X :\ else if 814,X is not 0 current section is not :\ complete BNE LEC3D :\ so EC3D INC &0810,X :\ else implement a section change LDA &0810,X :\ check if its complete CMP #&03 :\ if not BNE LEC2D :\ goto EC2D LDY &0820,X :\ else set A from LDA &08C0,Y :\ &820 and &8C0 (first envelope byte) BMI LEC59 :\ if negative there is no repeat LDA #&00 :\ else restart section sequence STA &0830,X :\ STA &0810,X :\ .LEC2D \get number of steps in new section LDA &0810,X :\ CLC :\ ADC &0820,X :\ TAY :\ LDA &08C4,Y :\ STA &0814,X :\ set in 814+X BEQ LEC59 :\ and if 0 then EC59 .LEC3D \decrement DEC &0814,X :\ LDA &0820,X :\ and pick up rate of pitch change CLC :\ ADC &0810,X :\ TAY :\ LDA &08C1,Y :\ CLC :\ ADC &0830,X :\ add to rate of differential pitch change STA &0830,X :\ and save it CLC :\ ADC &080C,X :\ ad to base pitch JSR LED01 :\ and set new pitch .LEC59 \if X=4 (last channel) CPX #&04 :\ BEQ LEC6A :\ goto EC6A (RTS) JMP LEB59 :\ else do loop again \ X=7 again .LEC60 LDX #&08 :\ .LEC62 \loop DEX :\ JSR LECA2 :\ clear channel CPX #&04 :\ if not 4 BNE LEC62 :\ do it again .LEC6A and return RTS :\ :\ \ check for last channel .LEC6B LDA &0808,X :\ CMP #&04 :\ is it 4 (release complete) BEQ LEC77 :\ if so EC77 LDA #&03 :\ else mark release in progress STA &0808,X :\ and store it .LEC77 \is buffer not empty LDA &02CF,X :\ BEQ LEC90 :\ if so EC90 LDA #&00 :\ else mark buffer not empty STA &02CF,X :\ an store it LDY #&04 :\ loop counter .LEC83 \zero sync bytes STA &082B,Y :\ DEY :\ BNE LEC83 :\ until Y=0 STA &0818,X :\ zero duration count DEY :\ and set sync count to STY &0838 :\ &FF .LEC90 \get synchronising flag LDA &0828,X :\ BEQ LECDB :\ if its 0 then ECDB LDA &083B :\ else get number of channels on hold BEQ LECD0 :\ if 0 then ECD0 LDA #&00 :\ else STA &0828,X :\ zero note length interval .LEC9F \and goto ED98 JMP LED98 :\ \ silence the channel .LECA2 JSR LEB03 :\ TYA :\ Y=0 A=Y STA &0818,X :\ zero main count STA &02CF,X :\ mark buffer not empty STA &0800,X :\ mark channel dormant LDY #&03 :\ loop counter .LECB1 \zero sync flags STA &082C,Y :\ DEY :\ BPL LECB1 :\ STY &0838 :\ number of channels to &FF BMI LED06 :\ jump to ED06 ALWAYS .LECBC \save flags PHP :\ SEI :\ and disable interrupts LDA &0808,X :\ check for end of release CMP #&04 :\ BNE LECCF :\ and if not found ECCF JSR LE45B :\ elseexamine buffer BCC LECCF :\ if not empty ECCF LDA #&00 :\ else mark channel dormant STA &0800,X :\ .LECCF \get back flags PLP :\ .LECD0 \if no envelope 820=&FF LDY &0820,X :\ CPY #&FF :\ BNE LECDA :\ then terminate sound JSR LEB03 :\ via EB03 .LECDA \else return RTS :\ \************ Synchronise sound routines ********************************** \ examine buffer if empty carry set .LECDB JSR LE45B :\ BCS LECBC :\ AND #&03 :\ else examine next word if>3 or 0 BEQ LEC9F :\ goto ED98 (via EC9F) LDA &0838 :\ else get synchronising count BEQ LECFE :\ in 0 (complete) goto ECFE INC &0828,X :\ else set sync flag BIT &0838 :\ if 0838 is +ve S has already been set so BPL LECFB :\ jump to ECFB JSR LE45B :\ else get first byte AND #&03 :\ mask bits 0,1 STA &0838 :\ and store result BPL LECFE :\ Jump to ECFE (ALWAYS!!) .LECFB \decrement 0838 DEC &0838 :\ .LECFE \and silence the channel if envelope not in use JMP LECD0 :\ \************ Pitch setting *********************************************** \ If A=&82C,X then pitch is unchanged .LED01 CMP &082C,X :\ BEQ LECDA :\ then exit via ECDA .LED06 \store new pitch STA &082C,X :\ CPX #&04 :\ if X<>4 then not noise so BNE LED16 :\ jump to ED16 \*********** Noise setting ************************************************ AND #&0F :\ convert to chip format ORA LEB3C,X :\ PHP :\ save flags JMP LED95 :\ and pass to chip control routine at EB22 via ED95 .LED16 PHA :\ AND #&03 :\ STA &083C :\ lose eigth tone surplus LDA #&00 :\ STA &083D :\ PLA :\ get back A LSR A :\ divide by 12 LSR A :\ .LED24 CMP #&0C :\ BCC LED2F :\ INC &083D :\ store result SBC #&0C :\ with remainder in A BNE LED24 :\ :\ at this point 83D defines the Octave :\ A the semitone within the octave .LED2F \Y=A TAY :\ LDA &083D :\ get octave number into A PHA :\ push it LDA LEDFB,Y :\ get byte from look up table STA &083D :\ store it LDA LEE07,Y :\ get byte from second table PHA :\ push it AND #&03 :\ keep two LS bits only STA &083E :\ save them PLA :\ pull second table byte LSR A :\ push hi nybble into lo nybble LSR A :\ LSR A :\ LSR A :\ STA &083F :\ store it LDA &083D :\ get back octave number LDY &083C :\ adjust for surplus eighth tones BEQ LED5F :\ .LED53 SEC :\ SBC &083F :\ BCS LED5C :\ DEC &083E :\ .LED5C DEY :\ BNE LED53 :\ .LED5F STA &083D :\ PLA :\ TAY :\ BEQ LED6F :\ .LED66 LSR &083E :\ ROR &083D :\ DEY :\ BNE LED66 :\ .LED6F LDA &083D :\ CLC :\ ADC LC43D,X :\ STA &083D :\ BCC LED7E :\ INC &083E :\ .LED7E AND #&0F :\ ORA LEB3C,X :\ PHP :\ push P SEI :\ bar interrupts JSR LEB21 :\ set up chip access 1 LDA &083D :\ LSR &083E :\ ROR A :\ LSR &083E :\ ROR A :\ LSR A :\ LSR A :\ .LED95 \set up chip access 2 and return JMP LEB22 :\ \**************** Pick up and interpret sound buffer data ***************** \ push flags .LED98 PHP :\ SEI :\ disable interrupts JSR LE460 :\ read a byte from buffer PHA :\ push A AND #&04 :\ isolate H bit BEQ LEDB7 :\ if 0 then EDB7 PLA :\ get back A LDY &0820,X :\ if &820,X=&FF CPY #&FF :\ envelope is not in use BNE LEDAD :\ JSR LEB03 :\ so call EB03 to silence channel .LEDAD \clear buffer of redundant data JSR LE460 :\ JSR LE460 :\ and again PLP :\ get back flags .LEDB4 \set main duration count using last byte from buffer JMP LEDF7 :\ \ get back A .LEDB7 PLA :\ AND #&F8 :\ zero bits 0-2 ASL A :\ put bit 7 into carry BCC LEDC8 :\ if zero (envelope) jump to EDC8 EOR #&FF :\ invert A LSR A :\ shift right SEC :\ SBC #&40 :\ subtract &40 JSR LEB0A :\ and set volume LDA #&FF :\ A=&FF .LEDC8 \get envelope no.-1 *16 into A STA &0820,X :\ LDA #&05 :\ set duration sub-counter STA &081C,X :\ LDA #&01 :\ set phase counter STA &0824,X :\ LDA #&00 :\ set step counter STA &0814,X :\ STA &0808,X :\ and envelope phase STA &0830,X :\ and pitch differential LDA #&FF :\ STA &0810,X :\ set step count JSR LE460 :\ read pitch STA &080C,X :\ set it JSR LE460 :\ read buffer PLP :\ PHA :\ save duration LDA &080C,X :\ get back pitch value JSR LED01 :\ and set it PLA :\ get back duration .LEDF7 \set it STA &0818,X :\ RTS :\ and return \********************* Pitch look up table 1***************************** \ EDFB DB &F0 .LEDFB BEQ LEDB4 :\ :\ EDFC DB &B7 EQUB &82 :\ EDFD DB &82 EQUB &4F :\ EDFE DB &4F JSR LC8F3 :\ EDFF DB &20 LDY #&7B :\ EE02 DB &A0 EQUB &57 :\ EE04 DB &57 AND &16,X :\ EE05 DB &35 .LEE07 \********************* Pitch look up table 2 ***************************** EQUB &E7 :\ EE07 DB &E7 EQUB &D7 :\ EE08 DB &D7 EQUB &CB :\ EE09 DB &CB EQUB &C3 :\ EE0A DB &C3 EQUB &B7 :\ EE0B DB &B7 TAX :\ EE0C DB &AA LDX #&9A :\ EE0D DB &A2 STA (&8A) :\ EE0F DB &92 EQUB &82 :\ EE11 DB &82 PLY :\ EE12 DB &7A .LEE13 \********* set current filing system ROM/PHROM ************************** LDA #&EF :\ get ROM STA &F5 :\ store it RTS :\ return .LEE18 \********** Get byte from data ROM *************************************** LDX #&0D :\ X=13 INC &F5 :\ LDY &F5 :\ get Rom BPL LEE59 :\ if +ve it's a sideways ROM else it's a PHROM LDX #&00 :\ PHROM STX &F7 :\ set address pointer in PHROM INX :\ STX &F6 :\ to 0001 JSR LEEBB :\ pass info to speech processor LDX #&03 :\ X=3 .LEE2C JSR LEE62 :\ check for speech processor and output until :\ it reports, read byte from ROM CMP LDF0C,X :\ if A<> DF0C+X then EE18 (DF0C = (C)) BNE LEE18 :\ DEX :\ else decrement X BPL LEE2C :\ and do it again LDA #&3E :\ STA &F6 :\ get noe lo byte address .LEE3B JSR LEEBB :\ pass info to speech processor LDX #&FF :\ .LEE40 JSR LEE62 :\ check for speech proc. etc. LDY #&08 :\ .LEE45 ASL A :\ ROR &F7,X :\ DEY :\ BNE LEE45 :\ INX :\ BEQ LEE40 :\ CLC :\ BCC LEEBB :\ .LEE51 \************ ROM SERVICE ************************************************ LDX #&0E :\ LDY &F5 :\ if Y is negative (PHROM) BMI LEE62 :\ GOTO EE62 LDY #&FF :\ else Y=255 .LEE59 PHP :\ push flags JSR LF168 :\ offer paged rom service PLP :\ pull processor flags CMP #&01 :\ if A>0 set carry TYA :\ A=Y RTS :\ return .LEE62 \********* PHROM SERVICE ************************************************* :\ PHP :\ push processor flags SEI :\ disable interrupts LDY #&10 :\ Y=16 JSR LEE7F :\ call EE7F (osbyte 159 write to speech processor LDY #&00 :\ Y=0 BEQ LEE84 :\ Jump to EE84 (ALWAYS!!) .LEE6D \************************************************************************* \* * \* OSBYTE 158 read from speech processor * \* * \************************************************************************* LDY #&00 :\ Y=0 to set speech proc to read BEQ LEE82 :\ jump to EE82 always .LEE71 \ :\ write A to speech processor as two nybbles PHA :\ push A JSR LEE7A :\ to write to speech processor PLA :\ get back A ROR A :\ bring upper nybble to lower nybble ROR A :\ by rotate right ROR A :\ 4 times ROR A :\ .LEE7A AND #&0F :\ Y=lo nybble A +&40 ORA #&40 :\ TAY :\ forming command for speech processor .LEE7F \************************************************************************* \* * \* OSBYTE 159 Write to speech processor * \* * \************************************************************************* \ on entry data or command in Y TYA :\ transfer command to A LDY #&01 :\ to set speech proc to write .LEE82 \ :\ if Y=0 read speech processor \ :\ if Y=1 write speech processor PHP :\ push flags SEI :\ disable interrupts .LEE84 BIT &027B :\ test for prescence of speech processor BPL LEEAA :\ if not there goto EEAA PHA :\ else push A LDA LF075,Y :\ STA LFE43 :\ set DDRA of system VIA to give 8 bit input (Y=0) :\ or 8 bit output (Y=1) PLA :\ get back A STA LFE4F :\ and send to speech chip LDA LF077,Y :\ output Prt B of system VIA STA LFE40 :\ to select read or write (dependent on Y) .LEE9A BIT LFE40 :\ loop until BMI LEE9A :\ speech proceessor reports ready (bit 7 Prt B=0) LDA LFE4F :\ read speech processor data if input selected PHA :\ push A LDA LF079,Y :\ reset speech STA LFE40 :\ processor PLA :\ get back A .LEEAA PLP :\ get back flags TAY :\ transfer A to Y RTS :\ and exit routine .LEEAD LDA &03CB :\ set rom displacement pointer STA &F6 :\ in &F6 LDA &03CC :\ STA &F7 :\ And &F7 LDA &F5 :\ if F5 is +ve ROM is selected so BPL LEED9 :\ goto EED9 .LEEBB PHP :\ else push processor SEI :\ disable interrupts LDA &F6 :\ get lo displacement JSR LEE71 :\ pass two nyblles to speech proc. LDA &F5 :\ &FA=&F5 STA &FA :\ LDA &F7 :\ get hi displacement value ROL A :\ replace two most significant bits of A ROL A :\ by 2 LSBs of &FA LSR &FA :\ ROR A :\ LSR &FA :\ ROR A :\ JSR LEE71 :\ pass two nybbles to speech processor LDA &FA :\ FA has now been divided by 4 so pass JSR LEE7A :\ lower nybble to speech proc. PLP :\ get back flags .LEED9 RTS :\ and Return .LEEDA \************ Keyboard Input and housekeeping ************************ \ :\ entered from &F00C LDX #&FF :\ LDA &EC :\ get value of most recently pressed key ORA &ED :\ Or it with previous key to check for presses BNE LEEE8 :\ if A=0 no keys pressed so off you go LDA #&81 :\ else enable keybd interupt only by writing bit 7 STA LFE4E :\ and bit 0 of system VIA interupt register INX :\ set X=0 .LEEE8 STX &0242 :\ reset keyboard semaphore .LEEEB \********** Turn on Keyboard indicators ******************************* PHP :\ save flags LDA &025A :\ read keyboard status; :\ Bit 7 =1 shift enabled :\ Bit 6 =1 control pressed :\ bit 5 =0 shift lock :\ Bit 4 =0 Caps lock :\ Bit 3 =1 shift pressed LSR A :\ shift Caps bit into bit 3 AND #&18 :\ mask out all but 4 and 3 ORA #&06 :\ returns 6 if caps lock OFF &E if on STA LFE40 :\ turn on or off caps light if required LSR A :\ bring shift bit into bit 3 ORA #&07 :\ STA LFE40 :\ turn on or off shift lock light JSR LF12E :\ set keyboard counter PLA :\ get back flags RTS :\ return \************************************************************************* \* * \* MAIN KEYBOARD HANDLING ROUTINE ENTRY FROM KEYV * \* ========================================================== * \* * \* ENTRY CONDITIONS * \* ================ * \* C=0, V=0 Test Shift and CTRL keys.. exit with N set if CTRL pressed * \* ........with V set if Shift pressed * \* * \* C=1, V=0 Scan Keyboard as OSBYTE &79 * \* * \* C=0, V=1 Key pressed interrupt entry * \* * \* C=1, V=1 Timer interrupt entry * \* * \************************************************************************* BVC LEF0E :\ if V is clear then leave interrupt routine LDA #&01 :\ disable keyboard interrupts STA LFE4E :\ by writing to VIA interrupt vector BCS LEF13 :\ if timer interrupt then EF13 JMP LF00F :\ else to F00F .LEF0E BCC LEF16 :\ if test SHFT & CTRL goto EF16 JMP LF0D1 :\ else to F0D1 .LEF13 :\ to scan keyboard \************************************************************************* \* Timer interrupt entry * \************************************************************************* INC &0242 :\ increment keyboard semaphore (to 0) .LEF16 \************************************************************************* \* Test Shift and Control Keys entry * \************************************************************************* LDA &025A :\ read keyboard status; \ :\ Bit 7 =1 shift enabled \ :\ Bit 6 =1 control pressed \ :\ bit 5 =0 shift lock \ :\ Bit 4 =0 Caps lock \ :\ Bit 3 =1 shift pressed AND #&B7 :\ zero bits 3 and 6 LDX #&00 :\ zero X to test for shift key press JSR LF02A :\ interrogate keyboard X=&80 if key determined by :\ X on entry is pressed STX &FA :\ save X CLV :\ clear V BPL LEF2A :\ if no key press (X=0) then EF2A else BIT LD9B7 :\ set M and V ORA #&08 :\ set bit 3 to indicate Shift was pressed .LEF2A INX :\ check the control key JSR LF02A :\ via keyboard interrogate BCC LEEEB :\ if carry clear (entry via EF16) then off to EEEB :\ to turn on keyboard lights as required BPL LEF34 :\ if key not pressed goto EF30 ORA #&40 :\ or set CTRL pressed bit in keyboard status byte in A .LEF34 STA &025A :\ save status byte LDX &EC :\ if no key previously pressed BEQ LEF4D :\ then EF4D JSR LF02A :\ else check to see if key still pressed BMI LEF50 :\ if so enter repeat routine at EF50 CPX &EC :\ else compare X with last key pressed (set flags) .LEF42 STX &EC :\ store X in last key pressed BNE LEF4D :\ if different from previous (Z clear) then EF4D LDX #&00 :\ else zero STX &EC :\ last key pressed .LEF4A JSR LF01F :\ and reset repeat system .LEF4D JMP LEFE9 :\ .LEF50 \********** REPEAT ACTION ************************************************* CPX &EC :\ if X<>than last key pressed BNE LEF42 :\ then back to EF42 LDA &E7 :\ else get value of AUTO REPEAT COUNTDOWN TIMER BEQ LEF7B :\ if 0 goto EF7B DEC &E7 :\ else decrement BNE LEF7B :\ and if not 0 goto EF7B :\ this means that either the repeat system is dormant :\ or it is not at the end of its count LDA &02CA :\ next value for countdown timer STA &E7 :\ store it LDA &0255 :\ get auto repeat rate from 0255 STA &02CA :\ store it as next value for Countdown timer LDA &025A :\ get keyboard status LDX &EC :\ get last key pressed CPX #&D0 :\ if not SHIFT LOCK key (&D0) goto BNE LEF7E :\ EF7E ORA #&90 :\ sets shift enabled, & no caps lock all else preserved EOR #&A0 :\ reverses shift lock disables Caps lock and Shift enab .LEF74 STA &025A :\ reset keyboard status LDA #&00 :\ and set timer STA &E7 :\ to 0 .LEF7B JMP LEFE9 :\ .LEF7E CPX #&C0 :\ if not CAPS LOCK BNE LEF91 :\ goto EF91 ORA #&A0 :\ sets shift enabled and disables SHIFT LOCK BIT &FA :\ if bit 7 not set by (EF20) shift NOT pressed BPL LEF8C :\ goto EF8C ORA #&10 :\ else set CAPS LOCK not enabled EOR #&80 :\ reverse SHIFT enabled .LEF8C EOR #&90 :\ reverse both SHIFT enabled and CAPs Lock JMP LEF74 :\ reset keyboard status and set timer .LEF91 \*********** get ASCII code ********************************************* :\ on entry X=key pressed internal number LDA LEFAB,X :\ get code from look up table BNE LEF99 :\ if not zero goto EF99 else TAB pressed LDA &026B :\ get TAB character .LEF99 LDX &025A :\ get keyboard status STX &FA :\ store it in &FA ROL &FA :\ rotate to get CTRL pressed into bit 7 BPL LEFA9 :\ if CTRL NOT pressed EFA9 LDX &ED :\ get no. of previously pressed key .LEFA4 BNE LEF4A :\ if not 0 goto EF4A to reset repeat system etc. JSR LEABF :\ else perform code changes for CTRL .LEFA9 ROL &FA :\ move shift lock into bit 7 .LEFAB BMI LEFB5 :\ if not effective goto EFB5 else JSR LEA9C :\ make code changes for SHIFT ROL &FA :\ move CAPS LOCK into bit 7 JMP LEFC1 :\ and Jump to EFC1 .LEFB5 ROL &FA :\ move CAPS LOCK into bit 7 BMI LEFC6 :\ if not effective goto EFC6 JSR LE4E3 :\ else make changes for CAPS LOCK on, return with :\ C clear for Alphabetic codes BCS LEFC6 :\ if carry set goto EFC6 else make changes for JSR LEA9C :\ SHIFT as above .LEFC1 LDX &025A :\ if shift enabled bit is clear BPL LEFD1 :\ goto EFD1 .LEFC6 ROL &FA :\ else get shift bit into 7 BPL LEFD1 :\ if not set goto EFD1 LDX &ED :\ get previous key press BNE LEFA4 :\ if not 0 reset repeat system etc. via EFA4 JSR LEA9C :\ else make code changes for SHIFT .LEFD1 CMP &026C :\ if A<> ESCAPE code BNE LEFDD :\ goto EFDD LDX &0275 :\ get Escape key status BNE LEFDD :\ if ESCAPE returns ASCII code goto EFDD STX &E7 :\ store in Auto repeat countdown timer .LEFDD TAY :\ JSR LF129 :\ disable keyboard LDA &0259 :\ read Keyboard disable flag used by Econet BNE LEFE9 :\ if keyboard locked goto EFE9 JSR LE4F1 :\ put character in input buffer .LEFE9 LDX &ED :\ get previous keypress BEQ LEFF8 :\ if none EFF8 JSR LF02A :\ examine to see if key still pressed STX &ED :\ store result BMI LEFF8 :\ if pressed goto EFF8 LDX #&00 :\ else zero X STX &ED :\ and &ED .LEFF8 LDX &ED :\ get &ED BNE LF012 :\ if not 0 goto F012 LDY #&EC :\ get first keypress into Y JSR LF0CC :\ scan keyboard from &10 (osbyte 122) BMI LF00C :\ if exit is negative goto F00C LDA &EC :\ else make last key the STA &ED :\ first key pressed i.e. rollover .LF007 STX &EC :\ save X into &EC JSR LF01F :\ set keyboard repeat delay .LF00C JMP LEEDA :\ go back to EEDA .LF00F \************************************************************************* \* Key pressed interrupt entry point * \************************************************************************* :\ enters with X=key JSR LF02A :\ check if key pressed .LF012 LDA &EC :\ get previous key press BNE LF00C :\ if none back to housekeeping routine LDY #&ED :\ get last keypress into Y JSR LF0CC :\ and scan keyboard BMI LF00C :\ if negative on exit back to housekeeping BPL LF007 :\ else back to store X and reset keyboard delay etc. .LF01F \**************** Set Autorepeat countdown timer ************************** LDX #&01 :\ set timer to 1 STX &E7 :\ LDX &0254 :\ get next timer value STX &02CA :\ and store it RTS :\ .LF02A \*************** Interrogate Keyboard routine *********************** :\ LDY #&03 :\ stop Auto scan STY LFE40 :\ by writing to system VIA LDY #&7F :\ set bits 0 to 6 of port A to input on bit 7 :\ output on bits 0 to 6 STY LFE43 :\ STX LFE4F :\ write X to Port A system VIA LDX LFE4F :\ read back &80 if key pressed (M set) RTS :\ and return \************************************************************************* \* * \* KEY TRANSLATION TABLES * \* * \* 7 BLOCKS interspersed with unrelated code * \************************************************************************* \key data block 1 ADC (&33),Y :\ F03B DB 71,33,34,35,84,38,87,2D,5E,8C \ :\ q ,3 ,4 ,5 ,f4,8 ,f7,- ,^ ,rt \************************************************************************* \* * \* OSBYTE 120 Write KEY pressed Data * \* * \************************************************************************* BIT &35,X :\ store Y as latest key pressed STY &38 :\ EQUB &87 :\ AND &8C5E :\ STY &EC :\ STX &ED :\ store X as previous key pressed RTS :\ and exit \key data block 2 \ \ F04A DB 80,77,65,74,37,69,39,30,5F,8E BRK :\ \ :\ f0,w ,e ,t ,7 ,i ,9 ,0 ,_ ,lft BRA LF0C4 :\ Jim paged entry vector ADC &74 :\ EQUB &37 :\ ADC #&39 :\ BMI LF0B3 :\ STX LFE6C :\ SBC LFA6C,X :\ \key data block 3 BRK :\ F05A DB 31,32,64,72,36,75,6F,70,5B,8F :\ 1 ,2 ,d ,r ,6 ,u ,o ,p ,[ ,dn \************************************************************************* \* * \* Main entry to keyboard routines * \* * \************************************************************************* AND (&32),Y :\ set V and M STZ &72 :\ ROL &75,X :\ EQUB &6F :\ BVS LF0BF :\ EQUB &8F :\ .LF065 BIT LD9B7 :\ .LF068 \i.e. KEYV JMP (&0228) :\ \key data block 4 \ F06B DB 01,61,78,66,79,6A,6B,40,3A,0D ORA (&61,X) :\ \ :\ CL,a ,x ,f ,y ,j ,k ,@ , ,RETN NEXTB CL=CAPS LOCK \speech routine data SEI :\ F075 DB 00,FF,01,02,09,0A ROR &79 :\ ROR A :\ EQUB &6B :\ RTI :\ DEC A :\ ORA LFF00 :\ .LF077 \key data block 5 ORA (&02,X) :\ F07B DB 02,73,63,67,68,6E,6C,3B,5D,7F .LF079 ORA #&0A :\ EQUB &02 :\ \ :\ SL,s ,c ,g ,h ,n ,l ,; ,] ,DEL NEXTBGET SL=SHIFT LOCK \************************************************************************* \* * \* OSBYTE 131 READ OSHWM (PAGE in BASIC) * \* * \************************************************************************* EQUB &73 :\ read current OSHWM EQUB &63 :\ EQUB &67 :\ PLA :\ ROR &3B6C :\ EOR &AC7F,X :\ EQUB &44 :\ EQUB &02 :\ LDX #&00 :\ RTS :\ \key data block 6 \ F08B DB 00 ,7A,20 ,76,62,6D,2C,2E,2F,8B BRK :\ \ :\ TAB,Z ,SPACE,V ,b ,m ,, ,. ,/ ,copy \***** set input buffer number and flush it ***************************** PLY :\ get current input buffer JSR &6276 :\ ADC &2E2C :\ EQUB &2F :\ EQUB &8B :\ .LF095 LDX &0241 :\ .LF098 \flush it JMP LE1AD :\ \ key data block 7 \ F09B DB 1B,81,82,83,85,86,88,89,5C,8D EQUB &1B :\ \ :\ ESC,f1,f2,f3,f5,f6,f8,f9,\ , STA (&82,X) :\ goto eventV handling routine EQUB &83 :\ STA &86 :\ DEY :\ BIT #&5C :\ STA &206C :\ \************************************************************************* \* * \* OSBYTE 15 FLUSH SELECTED BUFFER CLASS * \* * \************************************************************************* \ :\ flush selected buffer \ :\ X=0 flush all buffers \ :\ X>1 flush input buffer EQUB &02 :\ if X<>1 flush input buffer only BNE LF095 :\ .LF0AA \else load highest buffer number (8) LDX #&08 :\ .LF0AC \allow interrupts CLI :\ SEI :\ briefly! JSR LF0B4 :\ flush buffer DEX :\ decrement X to point at next buffer BPL LF0AC :\ if X>=0 flush next buffer \ :\ at this point X=255 \************************************************************************* \* * \* OSBYTE 21 FLUSH SPECIFIC BUFFER * \* * \************************************************************************* \on entry X=buffer number .LF0B4 \is X<9? CPX #&09 :\ BCC LF098 :\ if so flush buffer or else RTS :\ exit \************************************************************************* \* * \* Issue *HELP to ROMS * \* * \************************************************************************* LDX #&09 :\ JSR LF168 :\ JSR LFA4A :\ print following message routine return after BRK ORA &534F :\ carriage return .LF0C4 \help message JSR &2E31 :\ carriage return AND (&30) :\ ORA &6000 :\ .LF0CC \************************************************************************* \* * \* OSBYTE 122 KEYBOARD SCAN FROM &10 (16) * \* * \************************************************************************* CLC :\ clear carry LDX #&10 :\ set X to 10 .LF0CF \************************************************************************* \* * \* OSBYTE 121 KEYBOARD SCAN FROM VALUE IN X * \* * \************************************************************************* BCS LF068 :\ if carry set (by osbyte 121) F068 .LF0D1 \ :\ Jmps via KEYV and hence back to; \************************************************************************* \* Scan Keyboard C=1, V=0 entry via KEYV * \************************************************************************* TXA :\ if X is +ve goto F0D9 BPL LF0D9 :\ JSR LF02A :\ else interrogate keyboard BCS LF12E :\ if carry set F12E to set Auto scan else .LF0D9 PHP :\ push flags BCC LF0DE :\ if carry clear goto FODE else LDY #&EE :\ set Y so next operation saves to 2cd .LF0DE STA &01DF,Y :\ can be 2cb,2cc or 2cd LDX #&09 :\ set X to 9 .LF0E3 JSR LF129 :\ select auto scan LDA #&7F :\ set port A for input on bit 7 others outputs STA LFE43 :\ LDA #&03 :\ stop auto scan STA LFE40 :\ LDA #&0F :\ select non-existent keyboard column F (0-9 only!) STA LFE4F :\ LDA #&01 :\ cancel keyboard interrupt STA LFE4D :\ STX LFE4F :\ select column X (9 max) BIT LFE4D :\ if bit 1 =0 there is no keyboard interrupt so BEQ LF123 :\ goto F123 TXA :\ else put column address in A .LF103 CMP &01DF,Y :\ compare with 1DF+Y BCC LF11E :\ if less then F11E STA LFE4F :\ else select column again BIT LFE4F :\ and if bit 7 is 0 BPL LF11E :\ then F11E PLP :\ else push and pull flags PHP :\ BCS LF127 :\ and if carry set goto F127 PHA :\ else Push A EOR &0000,Y :\ EOR with EC,ED, or EE depending on Y value ASL A :\ shift left CMP #&01 :\ set carry if = or greater than number holds EC,ED,EE PLA :\ get back A BCS LF127 :\ if carry set F127 .LF11E CLC :\ else clear carry ADC #&10 :\ add 16 BPL LF103 :\ and do it again if 0==3 C set X=3 Z set JMP LF14B :\ .LF140 \******** set cassette options ******************************************* \ :\ called after BREAK etc \ :\ lower nybble sets sequential access \ :\ upper sets load and save options \ \ :\ 0000 Ignore errors, no messages \ :\ 0001 Abort if error, no messages \ :\ 0010 Retry after error, no messages \ :\ 1000 Ignore error short messages \ :\ 1001 Abort if error short messages \ :\ 1010 Retry after error short messages \ :\ 1100 Ignore error long messages \ :\ 1101 Abort if error long messages \ :\ 1110 Retry after error long messages PHP :\ save flags LDA #&A1 :\ set sequential access abort if error, no messages STA &E3 :\ set load/save retry if error, short messages LDA #&19 :\ set interblock gap STA &03D1 :\ and store it PLP :\ get back flags .LF14B PHP :\ push flags LDA #&06 :\ get close files command to FSCV JSR LE031 :\ and gosub OSFSC LDX #&06 :\ PLP :\ get back flags BEQ LF157 :\ if Z set earlier DEX :\ do not decrement X .LF157 STX &C6 :\ set current baud rate X=5 300 baud X=6 1200 baud \********* reset FILEV,ARGSV,BGETV,BPUTV,GBPBV,FINDV,FSCV ****************** \********** to F27D, F18E, F4C9, F529, FFA6, F3CA, F1B1 ****************** LDX #&0E :\ RESET VECTORS FOR FILE RELATED OPERATIONS .LF15B LDA LD951,X :\ STA &0211,X :\ DEX :\ BNE LF15B :\ STX &C2 :\ &C2=0 PROGRESS FLAG LDX #&0F :\ set X to make Rom service call &F claim vectors! .LF168 \************************************************************************* \* * \* OSBYTE 143 * \* Pass service commands to sideways ROMs * \* * \************************************************************************* \ :\ On entry X=service call number \ :\ Y=any additional parameter \ :\ On entry X=0 if claimed, or preserved if unclaimed \ :\ Y=any returned parameter \ :\ When called internally, EQ set if call claimed LDA &F4 :\ Get current ROM number PHA :\ Save it TXA :\ Pass service call number to A LDX #&0F :\ Start at ROM 15 .LF16E \ :\ Issue service call loop INC &02A1,X :\ Read bit 7 on ROM type table (no ROM has type 254 &FE) DEC &02A1,X :\ BPL LF183 :\ If not set (+ve result), step to next ROM down STX &F4 :\ Otherwise, select this ROM, &F4 RAM copy STX LFE30 :\ Page in selected ROM JSR &8003 :\ Call the ROM's service entry :\ X and P do not need to be preserved by the ROM TAX :\ On exit pass A to X to chech if claimed BEQ LF186 :\ If 0, service call claimed, reselect ROM and exit LDX &F4 :\ Otherwise, get current ROM back .LF183 DEX :\ Step to next ROM down BPL LF16E :\ Loop until done ROM 0 .LF186 PLA :\ Get back original ROM number STA &F4 :\ Set ROM number RAM copy STA LFE30 :\ Page in the original ROM TXA :\ Pass X back to A to set zero flag RTS :\ And return \************************************************************************* \* * \* CFS OSARGS entry point * \* \************************************************************************* ORA #&00 :\ is A=00 BNE LF1A2 :\ if not return CPY #&00 :\ is Y=0 BNE LF1A2 :\ if not return LDA &C6 :\ else get current baud rate and zero bit 2 AND #&FB :\ C6=5 becomes 1, 6 becomes 2 ORA &0247 :\ if cassette selected A=0 else A=2 ASL A :\ multiply by 2 ORA &0247 :\ Or it again LSR A :\ divide by 2 .LF1A2 RTS :\ return cassette =0 .LF1A3 \************************************************************************* \* * \* FSC VECTOR TABLE * \* * \************************************************************************* JMP &1DF5 :\ *OPT (F54C) INC &04,X :\ */ (F304) EQUB &F3 :\ unknown command (E30F) EQUB &0F :\ EQUB &E3 :\ *RUN (F304) TSB &F3 :\ ROL A :\ *CAT (F32A) EQUB &F3 :\ osbyte 77 (E274) STZ &E2,X :\ \************************************************************************* \* Filing System control entry OSFSC * \* Entry via 021E FSCV * \* A= index 0 to 7 * \************************************************************************* \ :\ on entry A is reason code \ :\ A=0 A *OPT command has been used X & Y are the 2 parameters \ :\ A=1 EOF is being checked, on entry X=File handle \ on Exit X=FF = EOF exists else 00 \ :\ A=2 A */ command has been used *RUN the file \ :\ A=3 An unrecognised OS command has ben used X,Y point at command \ :\ A=4 A *RUN command has been used X,Y point at filename \ :\ A=5 A *CAT cammand has been issued X,Y point to rest of command \ :\ A=6 New filing system about to take over, close SPOOL & EXEC files \ :\ A=7 Return in X and Y lowest and highest file handle used \ :\ A=8 OS about to process *command CMP #&07 :\ if A>6 BCS LF1A2 :\ goto F1A2 (RTS) STX &BC :\ else save X ASL A :\ A=A*2 TAX :\ X=A to get offset LDA LF1A4,X :\ get hi byte of address PHA :\ push it LDA LF1A3,X :\ get lo byte of address PHA :\ push it LDX &BC :\ get back X RTS :\ this now jumps to the address got from the table +1 :\ the next RTS takes us back to CLI \************************************************************************* \* * \* LOAD FILE * \* * \************************************************************************* \ save flags on stack .LF1C4 PHP :\ PHA :\ save A on stack JSR LFB27 :\ Set cassette optionsinto (BB),set C7=6 :\ claim serial system for cassette LDA &03C2 :\ execution address LO PHA :\ save A on stack JSR LF631 :\ search for file PLA :\ get back A BEQ LF1ED :\ if A=0 F1ED LDX #&03 :\ else X=3 LDA #&FF :\ A=&FF .LF1D7 \save A on stack PHA :\ LDA &03BE,X :\ get load address STA &B0,X :\ store it as current load address PLA :\ get back A AND &B0,X :\ DEX :\ X=X-1 BPL LF1D7 :\ until all 4 bytes copied CMP #&FF :\ if all bytes contain don't contain &FF BNE LF1ED :\ continue JSR LFAE8 :\ else sound bell, reset ACIA & motor off JMP LE267 :\ 'Bad Address' error \ block flag .LF1ED LDA &03CA :\ LSR A :\ set carry from bit 0 PLA :\ get back A BEQ LF202 :\ if A=0 F202 BCC LF209 :\ if carry clear F209 \*************** LOCKED FILE ROUTINE ************************************* .LF1F6 \enable second processor and reset serial system JSR LFAF2 :\ BRK :\ CMP &4C,X :\ error number EQUB &6F :\ EQUB &63 :\ EQUB &6B :\ ADC &64 :\ BRK :\ .LF202 \if carry clear F209 BCC LF209 :\ LDA #&03 :\ else A=3 STA &0258 :\ store to cause ESCAPE disable and memory :\ clear on break .LF209 LDA #&30 :\ AND &BB :\ current OPTions BEQ LF213 :\ if options and #&30 =0 ignore error condition is set LDA &C1 :\ else get checksum result BNE LF21D :\ and if not 0 F21D .LF213 \A=Y TYA :\ PHA :\ save A on stack JSR LFBBB :\ read from second processor if present PLA :\ get back A TAY :\ Y=A JSR LF7D5 :\ reset flags and check block length .LF21D \load file from tape JSR LF9B4 :\ BNE LF255 :\ if not found return to search JSR LFB69 :\ increment current block number BIT &03CA :\ block flag BMI LF232 :\ if bit 7=1 then this is last block so F232 JSR LF96A :\ else increment current load address JSR LF77B :\ read block header BNE LF209 :\ and goto F209 \******** store data in OSFILE parameter block *************************** .LF232 \Y=&0A LDY #&0A :\ LDA &CC :\ file length counter lo STA (&C8),Y :\ OSFILE parameter block INY :\ Y=Y+1 LDA &CD :\ file length counter hi STA (&C8),Y :\ OSFILE parameter block LDA #&00 :\ A=0 INY :\ Y=Y+1 STA (&C8),Y :\ OSFILE parameter block INY :\ Y=Y+1 STA (&C8),Y :\ OSFILE parameter block PLP :\ get back flags .LF246 \bell, reset ACIA & motor JSR LFAE8 :\ .LF249 \current block flag BIT &BA :\ BMI LF254 :\ return .LF24D \save flags on stack PHP :\ JSR LFA46 :\ print message following call (in this case NEWLINE!) ORA &2800 :\ message .LF254 \return RTS :\ :\ \************RETRY AFTER A FAILURE ROUTINE ******************************* \ search for a specified block .LF255 JSR LF637 :\ BNE LF209 :\ goto F209 \*********** Read Filename using Command Line Interpreter **************** \filename pointed to by X and Y .LF25A \OS filename/command line pointer lo STX &F2 :\ STY &F3 :\ OS filename/command line pointer LDY #&00 :\ Y=0 JSR LEA1D :\ initialise string LDX #&00 :\ X=0 .LF265 \GSREAD call JSR LEA2F :\ BCS LF277 :\ if end of character string F277 BEQ LF274 :\ if 0 found F274 STA &03D2,X :\ else store character in CFS filename area INX :\ X=X+1 CPX #&0B :\ if X<>11 BNE LF265 :\ then read next .LF274 \else Bad String error JMP LEA8F :\ \************* terminate Filename **************************************** \ terminate filename with 0 .LF277 LDA #&00 :\ STA &03D2,X :\ RTS :\ return \************************************************************************* \* * \* OSFILE ENTRY * \* * \* on entry A determines action * \* A=0 save block of memory as a file * \* A=1 write catalogue info for existing file * \* A=2 write load address only for existing file * \* A=3 write execution address only for existing file * \* A=4 write attributes only for existing file * \* A=5 Read catalogue info, return file type in A * \* A=6 Delete named file * \* A=&FF load the named file if lo byte of Exec address=0 use * \* address in parameter block else files own load address * \* X,Y point to parameter block * \* bytes 0,1 filename address, 2-5 load,6-9 exec,A-D length or * \* start of data for save, 0E End address /attributes * \************************************************************************* \parameter block located by XY \0/1 Address of Filename terminated by &0D \2/4 Load Address of File \6/9 Execution Address of File \A/D Start address of data for write operations or length of file \ for read operations \E/11 End address of Data; i.e. byte AFTER last byte to be written \ or file attributes \ \On Entry action is determined by value in A \ \A=0 Save section of memory as named file, write catalogue information \A=1 Write catalogue information for named file \A=2 Write the LOAD address (only) for the named File \A=3 Write the EXECUTION address (only) for the named File \A=4 Write the ATTRIBUTES for the named File \A=5 Read the named files catalogue information Place file type in A \A=6 Delete the named file \A=&FF Load the named file and read its catalogue information \ save A on stack PHA :\ STX &C8 :\ osfile block pointer lo STY &C9 :\ osfile block pointer hi LDY #&00 :\ Y=0 LDA (&C8),Y :\ OSFILE parameter block TAX :\ X=A INY :\ Y=Y+1 LDA (&C8),Y :\ OSFILE parameter block TAY :\ Y=A JSR LF25A :\ get filename from BUFFER LDY #&02 :\ Y=2 .LF290 \copy parameters to Cassette block at 3BE/C5 LDA (&C8),Y :\ STA &03BC,Y :\ from LOAD and EXEC address STA &00AE,Y :\ make second copy at B0-B8 INY :\ Y=Y+1 CPY #&0A :\ until Y=10 BNE LF290 :\ PLA :\ get back A BEQ LF2A7 :\ if A=0 F2A7 CMP #&FF :\ else if A<>&FF BNE LF254 :\ RETURN as cassette has no other options JMP LF1C4 :\ load file \************** Save a file ********************************************** \ zero block number .LF2A7 STA &03C6 :\ STA &03C7 :\ zero block number hi .LF2AD \OSFILE parameter block LDA (&C8),Y :\ STA &00A6,Y :\ store to Zero page copy (&B0 to &B7) INY :\ data start and data end address CPY #&12 :\ until Y=18 BNE LF2AD :\ TXA :\ A=X BEQ LF274 :\ if X=0 no filename found so B274 else BAD STRING error JSR LFB27 :\ Set cassette option sinto (BB),set C7=6 :\ claim serial system for cassette JSR LF934 :\ prompt to start recording LDA #&00 :\ A=0 JSR LFBBD :\ enable 2nd proc. if present and set up osfile block JSR LFBE2 :\ set up CFS for write operation .LF2C8 \set carry flag SEC :\ LDX #&FD :\ X=&FD .LF2CB \set 03C8/A block length and block flag LDA LFFB7,X :\ SBC LFFB3,X :\ to B4/6-B0/2 the number of pages (blocks) to be :\ saved STA &02CB,X :\ INX :\ X=X+1 BNE LF2CB :\ TAY :\ Y=A BNE LF2E8 :\ if last byte is non zero F2E8 else CPX &03C8 :\ compare X with block length LDA #&01 :\ A=1 SBC &03C9 :\ subtract block length hi BCC LF2E8 :\ if carry clear F2E8 LDX #&80 :\ X=&80 BNE LF2F0 :\ jump F2F0 .LF2E8 \A=1 LDA #&01 :\ STA &03C9 :\ block length hi STX &03C8 :\ block length .LF2F0 \block flag STX &03CA :\ JSR LF7EC :\ write block to Tape BMI LF341 :\ return if negative JSR LF96A :\ increment current load address INC &03C6 :\ block number BNE LF2C8 :\ if not 0 loop back again else INC &03C7 :\ block number hi BNE LF2C8 :\ and loop back again \************************************************************************* \* * \* *RUN ENTRY * \* * \************************************************************************* .LF304 JSR LF25A :\ get filename from BUFFER LDX #&FF :\ X=&FF STX &03C2 :\ execution address JSR LF1C4 :\ load file BIT &027A :\ &FF if tube present BPL LF31F :\ so if not present F31F else LDA &03C4 :\ execution address extend AND &03C5 :\ execution address extend CMP #&FF :\ if they are NOT both &FF i.e.for base processor BNE LF322 :\ F322 else .LF31F :\ RUN file JMP (&03C2) :\ \ point to execution address .LF322 LDX #&C2 :\ LDY #&03 :\ (&03C2) LDA #&04 :\ Tube call 4 JMP LFBC7 :\ and issue to Tube to run file \************************************************************************* \* * \* *CAT ENTRY * \* * \************************************************************************* \ :\ CASSETTE OPTIONS in &E2 \ \ :\ bit 0 input file open \ :\ bit 1 output file open \ :\ bit 2,4,5 not used \ :\ bit 3 current CATalogue status \ :\ bit 6 EOF reached \ :\ bit 7 EOF warning given \ A=8 LDA #&08 :\ JSR LF344 :\ set status bits from A JSR LFB27 :\ Set cassette options into (BB),set C7=6 :\ claim serial system for cassette LDA #&00 :\ A=0 JSR LF348 :\ read data from CFS/RFS JSR LFAFC :\ perform read .LF33B \A=&F7 LDA #&F7 :\ .LF33D \clear bit 3 of CFS status bit AND &E2 :\ .LF33F STA &E2 :\ .LF341 \return RTS :\ \ set bit 6 of E2 cassette options .LF342 LDA #&40 :\ .LF344 ORA &E2 :\ BNE LF33F :\ and Jump F33F \********** search routine *********************************************** .LF348 \save A on stack PHA :\ LDA &0247 :\ filing system flag 0=CFS 2=RFS BEQ LF359 :\ if CFS F359 else JSR LEE13 :\ set current Filing System ROM/PHROM JSR LEE18 :\ get byte from data Romcheck type BCC LF359 :\ if carry clear F359 else CLV :\ clear overflow flag BVC LF39A :\ JUMP F39A \*********** cassette routine******************************************** .LF359 \read block header JSR LF77B :\ LDA &03C6 :\ block number STA &B4 :\ current block no. lo LDA &03C7 :\ block number hi STA &B5 :\ current block no. hi LDX #&FF :\ X=&FF STX &03DF :\ copy of last read block flag INX :\ X=X+1 STX &BA :\ current block flag BEQ LF376 :\ if 0 F376 .LF370 \inc. current block no. JSR LFB69 :\ JSR LF77B :\ read block header .LF376 \get filing system flag 0=CFS 2=RFS LDA &0247 :\ BEQ LF37D :\ if CFS F37D BVC LF39A :\ if V clear F39A .LF37D \get back A PLA :\ PHA :\ save A on stack BEQ LF3AE :\ if A=0 F3AE JSR LFA72 :\ else check filename header block matches searched Fn BNE LF39C :\ if so F39C LDA #&30 :\ else A=30 to clear all but bits 4/5 of current OPTions AND &BB :\ current OPTions BEQ LF39A :\ if 0 F39A else LDA &03C6 :\ block number CMP &B6 :\ next block no. lo BNE LF39C :\ LDA &03C7 :\ block number hi CMP &B7 :\ next block no. hi BNE LF39C :\ .LF39A \get back A PLA :\ RTS :\ return \ :\ \ filing system flag 0=CFS 2=RFS .LF39C LDA &0247 :\ BEQ LF3AE :\ if tape F3AE .LF3A1 \else set ROM displacement address JSR LEEAD :\ .LF3A4 \A=&FF LDA #&FF :\ STA &03C6 :\ block number STA &03C7 :\ block number hi BNE LF370 :\ jump F370 .LF3AE \if carry clear F3B5 BVC LF3B5 :\ LDA #&FF :\ A=&FF JSR LF7D7 :\ set flags .LF3B5 \X=0 LDX #&00 :\ JSR LF9D9 :\ report 'DATA?' LDA &0247 :\ filing system flag 0=CFS 2=RFS BEQ LF3C3 :\ BIT &BB :\ current OPTions BVC LF3A1 :\ long messages not required if BIT 6 =0 .LF3C3 \block flag BIT &03CA :\ BMI LF3A4 :\ if -ve F3A4 BPL LF370 :\ else loop back and do it again \************************************************************************* \* * \* OSFIND ENTRY * \* file handling * \* * \************************************************************************* \on entry A determines Action Y may contain file handle or \X/Y point to filename terminated by &0D in memory \A=0 closes file in channel Y if Y=0 closes all files \A=&40 open a file for input (reading) X/Y points to filename \A=&80 open a file for output (writing) X/Y points to filename \A=&C0 open a file for input and output (random access) \ON EXIT Y=0 if no file found else Y=channel number in use for file :\ save A X and Y STA &BC :\ file status or temporary store TXA :\ A=X PHA :\ save X on stack TYA :\ A=Y PHA :\ save Y on stack LDA &BC :\ file status or temporary store BNE LF3F2 :\ if A is non zero open a file via F3F2 \************ close a file *********************************************** TYA :\ A=Y BNE LF3E3 :\ if A<> 0 close specified file else close them all JSR LE275 :\ close spool/exec files via OSBYTE 77 JSR LF478 :\ tidy up .LF3DD \CFS status byte is shifted left and right to zero LSR &E2 :\ ASL &E2 :\ bit 0 BCC LF3EF :\ and if carry clear no input file was open so F3EF .LF3E3 \A contains file handle so shift bit 0 into carry LSR A :\ BCS LF3DD :\ if carry set close input file LSR A :\ else shift bit 1 into carry BCS LF3EC :\ if carry set close output file JMP LFBB1 :\ else report 'Channel Error' as CFS can only support :\ 1 input and 1 output file \ tidy up .LF3EC JSR LF478 :\ .LF3EF \and exit JMP LF471 :\ \************ OPEN A FILE ************************************************ \ get filename from BUFFER .LF3F2 JSR LF25A :\ BIT &BC :\ file status or temporary store BVC LF436 :\ check A at input if bit 6 not set its an output file \********* Input files +************************************************** LDA #&00 :\ else its an input file STA &039E :\ BGET buffer offset for next byte STA &03DD :\ Expected BGET file block number lo STA &03DE :\ expected BGET file block number hi LDA #&3E :\ A=&3E JSR LF33D :\ CFS status =CFS status AND A JSR LFB1A :\ claim serial system and set OPTions PHP :\ save flags on stack JSR LF631 :\ search for file JSR LF6B4 :\ check protection bit of block status and respond PLP :\ get back flags LDX #&FF :\ X=&FF increment to 0 on next instruction .LF416 \X=X+1 INX :\ LDA &03B2,X :\ get file name and STA &03A7,X :\ store as BGET filename BNE LF416 :\ until end of filename LDA #&01 :\ A=1 to show file open JSR LF344 :\ set status bits from A LDA &02EA :\ CFS currently resident file block length lo ORA &02EB :\ CFS currently resident file block length hi BNE LF42F :\ if block length is 0 JSR LF342 :\ set CFS status bit 3 (EOF reached) :\ else .LF42F \A=1 LDA #&01 :\ ORA &0247 :\ filing system flag 0=CFS 2=RFS BNE LF46F :\ and exit after restoring registers \******************* open an output file*********************************** .LF436 \A=X TXA :\ BNE LF43C :\ if X=0 then zero length filename so JMP LEA8F :\ Bad String error \ X=&FF .LF43C LDX #&FF :\ .LF43E \X=X+1 INX :\ :\ copy sought filename to header block LDA &03D2,X :\ sought filename STA &0380,X :\ BPUT file header block BNE LF43E :\ until A=0 end of filename LDA #&FF :\ A=&FF LDX #&08 :\ X=8 .LF44B \set 38C/93 to &FF STA &038B,X :\ DEX :\ X=X-1 BNE LF44B :\ TXA :\ A=X=0 LDX #&14 :\ X=14 .LF454 \BPUT file header block STA &0380,X :\ INX :\ X=X+1 CPX #&1E :\ this zeros 394/D BNE LF454 :\ ROL &0397 :\ JSR LFB27 :\ Set cassette optionsinto (BB),set C7=6 :\ claim serial system for cassette JSR LF934 :\ prompt to start recording JSR LFAF2 :\ enable second processor and reset serial system LDA #&02 :\ A=2 JSR LF344 :\ set status bits from A LDA #&02 :\ A=2 .LF46F \file status or temporary store STA &BC :\ .LF471 \get back A PLA :\ TAY :\ Y=A PLA :\ get back A TAX :\ X=A LDA &BC :\ file status or temporary store .LF477 \return RTS :\ \ :\ \ \ A=2 clearing all but bit 1 of status byte .LF478 LDA #&02 :\ AND &E2 :\ CFS status byte, with output file open BEQ LF477 :\ if file not open then exit LDA #&00 :\ else A=0 STA &0397 :\ setting block length to current value of BPUT offset LDA #&80 :\ A=&80 LDX &039D :\ get BPUT buffer ofset STX &0396 :\ setting block length to current value of BPUT offset STA &0398 :\ mark current block as last JSR LF496 :\ save block to tape LDA #&FD :\ A=&FD JMP LF33D :\ CFS status =CFS status AND A \*********** SAVE BLOCK TO TAPE ******************************************** \ claim serial system and set OPTions .LF496 JSR LFB1A :\ LDX #&11 :\ X=11 .LF49B \copy header block from 38C-39D LDA &038C,X :\ STA &03BE,X :\ to 3BE/DF DEX :\ X=X-1 BPL LF49B :\ :\ X=&FF STX &B2 :\ current load address high word STX &B3 :\ current load address high word INX :\ X=X+1, (X=0) STX &B0 :\ current load address lo byte set to &00 LDA #&09 :\ A=9 to set current load address at &900 STA &B1 :\ current load address LDX #&7F :\ X=&7F JSR LFB81 :\ copy from 301/C+X to 3D2/C sought filename STA &03DF :\ copy of last read block flag JSR LFB8E :\ switch Motor On JSR LFBE2 :\ set up CFS for write operation JSR LF7EC :\ write block to Tape INC &0394 :\ block number lo BNE LF4C8 :\ INC &0395 :\ block number hi .LF4C8 \return RTS :\ \************************************************************************* \* * \* * \* OSBGET get a byte from a file * \* * \* * \************************************************************************* :\ on ENTRY Y contains channel number :\ on EXIT X and Y are preserved C=0 indicates valid character :\ A contains character (or error) A=&FE End Of File :\ push X and Y \ A=X TXA :\ PHA :\ save A on stack TYA :\ A=Y PHA :\ save A on stack LDA #&01 :\ A=1 JSR LFB9C :\ check conditions for OSBGET are OK LDA &E2 :\ CFS status byte ASL A :\ shift bit 7 into carry (EOF warning given) BCS LF523 :\ if carry set F523 ASL A :\ shift bit 6 into carry .LF4D8 \if clear EOF not reached F4E3 BCC LF4E3 :\ LDA #&80 :\ else A=&80 setting bit 7 of status byte EOF warning JSR LF344 :\ set status bits from A LDA #&FE :\ A=&FE BCS LF51B :\ if carry set F51B .LF4E3 \BGET buffer offset for next byte LDX &039E :\ INX :\ X=X+1 CPX &02EA :\ CFS currently resident file block length lo BNE LF516 :\ read a byte :\ else BIT &02EC :\ block flag of currently resident block BMI LF513 :\ if bit 7=1 this is the last block so F513 else LDA &02ED :\ last character of currently resident block PHA :\ save A on stack JSR LFB1A :\ claim serial system and set OPTions PHP :\ save flags on stack JSR LF6AC :\ read in a new block PLP :\ get back flags PLA :\ get back A STA &BC :\ file status or temporary store CLC :\ clear carry flag BIT &02EC :\ block flag of currently resident block BPL LF51D :\ if not last block (bit 7=0) LDA &02EA :\ CFS currently resident file block length lo ORA &02EB :\ CFS currently resident file block length hi BNE LF51D :\ if block size not 0 F51D else JSR LF342 :\ set CFS status bit 6 (EOF reached) BNE LF51D :\ goto F51D .LF513 \set CFS status bit 6 (EOF reached) JSR LF342 :\ .LF516 \X=X-1 DEX :\ CLC :\ clear carry flag LDA &0A00,X :\ read byte from cassette buffer .LF51B \file status or temporary store STA &BC :\ .LF51D \BGET buffer offset for next byte INC &039E :\ JMP LF471 :\ exit via F471 .LF523 BRK :\ EQUB &DF :\ error number EOR &4F :\ LSR &00 :\ \************************************************************************* \* * \* * \* OSBPUT WRITE A BYTE TO FILE * \* * \* * \************************************************************************* \ON ENTRY Y contains channel number A contains byte to be written STA &C4 :\ store A in temorary store TXA :\ and stack X and Y PHA :\ save on stack TYA :\ A=Y PHA :\ save on stack LDA #&02 :\ A=2 JSR LFB9C :\ check conditions necessary for OSBPUT are OK LDX &039D :\ BPUT buffer offset for next byte LDA &C4 :\ get back original value of A STA &0900,X :\ Cassette buffer INX :\ X=X+1 BNE LF545 :\ if not 0 F545, otherwise buffer is full so JSR LF496 :\ save block to tape JSR LFAF2 :\ enable second processor and reset serial system .LF545 INC &039D :\ BPUT buffer offset for next byte LDA &C4 :\ get back A JMP LF46F :\ and exit \************************************************************************* \* * \* * \* OSBYTE 139 Select file options * \* * \* * \************************************************************************* \ON ENTRY Y contains option value X contains option No. see *OPT X,Y \this applies largely to CFS LOAD SAVE CAT and RUN \X=1 is message switch \ Y=0 no messages \ Y=1 short messages \ Y=2 gives detailed information on load and execution addresses \X=2 is error handling \ Y=0 ignore errors \ Y=1 prompt for a retry \ Y=2 abort operation \X=3 is interblock gap for BPUT# and PRINT# \ Y=0-127 set gap in 1/10ths Second \ Y > 127 use default values TXA :\ A=X BEQ LF57E :\ if A=0 F57E CPX #&03 :\ if X=3 BEQ LF573 :\ F573 to set interblock gap CPY #&03 :\ else if Y>2 then BAD COMMAND error BCS LF55E :\ DEX :\ X=X-1 BEQ LF561 :\ i.e. if X=1 F561 message control DEX :\ X=X-1 BEQ LF568 :\ i.e. if X=2 F568 error response .LF55E JMP LE310 :\ else E310 to issue Bad Command error .LF561 \*********** message control ********************************************* LDA #&33 :\ to set lower two bits of each nybble as mask INY :\ Y=Y+1 INY :\ Y=Y+1 INY :\ Y=Y+1 BNE LF56A :\ goto F56A .LF568 \*********** error response ********************************************* LDA #&CC :\ setting top two bits of each nybble as mask .LF56A INY :\ Y=Y+1 AND &E3 :\ clear lower two bits of each nybble .LF56D ORA LF581,Y :\ or with table value STA &E3 :\ store it in &E3 RTS :\ return .LF573 :\ setting of &E3 :\ :\ lower nybble sets LOAD options :\ upper sets SAVE options :\ 0000 Ignore errors, no messages :\ 0001 Abort if error, no messages :\ 0010 Retry after error, no messages :\ 1000 Ignore error short messages :\ 1001 Abort if error short messages :\ 1010 Retry after error short messages :\ 1100 Ignore error long messages :\ 1101 Abort if error long messages :\ 1110 Retry after error long messages \***********set interblock gap ******************************************* TYA :\ A=Y BMI LF578 :\ if Y>127 use default values BNE LF57A :\ if Y<>0 skip next instruction .LF578 LDA #&19 :\ else A=&19 .LF57A STA &03D1 :\ sequential block gap RTS :\ return .LF57E TAY :\ Y=A BEQ LF56D :\ jump to F56D .LF581 \*********** DEFAULT OPT VALUES TABLE ************************************ LDA (&00,X) :\ %1010 0001 EQUB &22 :\ %0010 0010 ORA (&00),Y :\ %0001 0001 DEY :\ %1000 1000 CPY LC0C6 :\ %1100 1100 LDA &0247 :\ filing system flag 0=CFS 2=RFS BEQ LF596 :\ if CFS F596 JSR LEE51 :\ read RFS data rom or Phrom TAY :\ Y=A CLC :\ clear carry flag BCC LF5B0 :\ jump to F5B0 .LF596 LDA LFE08 :\ ACIA status register PHA :\ save A on stack AND #&02 :\ clear all but bits 0,1 A=(0-3) BEQ LF5A9 :\ if 0 F5A9 transmit data register full or RDR empty LDY &CA :\ BEQ LF5A9 :\ PLA :\ get back A LDA &BD :\ character temporary storage STA LFE09 :\ ACIA transmit data register RTS :\ return .LF5A9 LDY LFE09 :\ read ACIA recieve data register PLA :\ get back A LSR A :\ bit 2 to carry (data carrier detect) LSR A :\ LSR A :\ .LF5B0 LDX &C2 :\ progress flag BEQ LF61D :\ if &C2=0 exit DEX :\ X=X-1 BNE LF5BD :\ if &C2>1 then F5BD BCC LF61D :\ else if carrier tone from cassette detected exit LDY #&02 :\ Y=2 BNE LF61B :\ .LF5BD DEX :\ X=X-1 BNE LF5D3 :\ if &C2>2 BCS LF61D :\ if carrier tone from cassette not detected exit TYA :\ A=Y JSR LFB78 :\ set (BE/C0) to 0 LDY #&03 :\ Y=3 CMP #&2A :\ is A= to synchronising byte &2A? BEQ LF61B :\ if so F61B JSR LFB50 :\ control cassette system LDY #&01 :\ Y=1 BNE LF61B :\ goto F61B .LF5D3 DEX :\ X=X-1 BNE LF5E2 :\ if &C2>3 BCS LF5DC :\ STY &BD :\ get character read into Y BEQ LF61D :\ if 0 exit via F61D .LF5DC LDA #&80 :\ else A=&80 STA &C0 :\ filing system buffer flag BNE LF61D :\ and exit .LF5E2 DEX :\ X=X-1 BNE LF60E :\ if &C2>4 F60E BCS LF616 :\ if carry set F616 TYA :\ A=Y JSR LF7B0 :\ perform CRC LDY &BC :\ file status or temporary store INC &BC :\ file status or temporary store BIT &BD :\ if bit 7 set this is the last byte read BMI LF600 :\ so F600 JSR LFBD3 :\ check if second processor file test tube prescence BEQ LF5FD :\ if return with A=0 F5FD STX LFEE5 :\ Tube FIFO3 BNE LF600 :\ .LF5FD TXA :\ A=X restore value STA (&B0),Y :\ store to current load address .LF600 INY :\ Y=Y+1 CPY &03C8 :\ block length BNE LF61D :\ exit LDA #&01 :\ A=1 STA &BC :\ file status or temporary store LDY #&05 :\ Y=5 BNE LF61B :\ exit .LF60E TYA :\ A=Y JSR LF7B0 :\ perform CRC DEC &BC :\ file status or temporary store BPL LF61D :\ exit .LF616 JSR LFB46 :\ reset ACIA LDY #&00 :\ Y=0 .LF61B STY &C2 :\ progress flag .LF61D RTS :\ return \************************************************************************* \* * \* FSCV &01 - check for end of file * \* * \************************************************************************* \ :\ PHA :\ save A on stack TYA :\ A=Y PHA :\ save Y on stack TXA :\ A=X to put X into Y TAY :\ Y=A LDA #&03 :\ A=3 JSR LFB9C :\ confirm file is open LDA &E2 :\ CFS status byte AND #&40 :\ TAX :\ X=A PLA :\ get back A TAY :\ Y=A PLA :\ get back A RTS :\ return .LF631 LDA #&00 :\ A=0 STA &B4 :\ current block no. lo STA &B5 :\ current block no. hi .LF637 LDA &B4 :\ current block no. lo PHA :\ save A on stack STA &B6 :\ next block no. lo LDA &B5 :\ current block no. hi PHA :\ save A on stack STA &B7 :\ next block no. hi JSR LFA46 :\ print message following call EQUB &53 :\ ADC &61 :\ newline ADC (&63) :\ PLA :\ ADC #&6E :\ EQUB &67 :\ ORA &A900 :\ EQUB &FF :\ read data from CFS/RFS JSR LF348 :\ PLA :\ get back A STA &B5 :\ current block no. hi PLA :\ get back A STA &B4 :\ current block no. lo LDA &B6 :\ next block no. lo ORA &B7 :\ next block no. hi BNE LF66D :\ STA &B4 :\ current block no. lo STA &B5 :\ current block no. hi LDA &C1 :\ checksum result BNE LF66D :\ LDX #&B1 :\ current load address JSR LFB81 :\ copy from 301/C+X to 3D2/C sought filename .LF66D \filing system flag 0=CFS 2=RFS LDA &0247 :\ BEQ LF685 :\ if cassette F685 BVS LF685 :\ .LF674 BRK :\ DEC &46,X :\ Error number :\ F676 DB 'File Not found' ADC #&6C :\ ADC &20 :\ ROR &746F :\ JSR &6F66 :\ ADC &6E,X :\ STZ &00 :\ .LF685 LDY #&FF :\ Y=&FF STY &03DF :\ copy of last read block flag RTS :\ return .LF68B \******** CLOSE EXEC FILE ********************************************** LDA #&00 :\ A=0 .LF68D \************************************************************************* \* * \* *EXEC * \* * \************************************************************************* PHP :\ save flags on stack STY &E6 :\ &E6=Y LDY &0256 :\ EXEC file handle STA &0256 :\ EXEC file handle BEQ LF69B :\ if not 0 close file via OSFIND JSR OSFIND :\ .LF69B LDY &E6 :\ else Y= original Y PLP :\ get back flags BEQ LF6AB :\ if A=0 on entry exit else LDA #&40 :\ A=&40 JSR OSFIND :\ to open an input file TAY :\ Y=A BEQ LF674 :\ If Y=0 'File not found' else store STA &0256 :\ EXEC file handle .LF6AB RTS :\ return .LF6AC \******* read a block ************************************************* LDX #&A6 :\ X=&A6 JSR LFB81 :\ copy from 301/C+X to 3D2/C sought filename JSR LF77B :\ read block header .LF6B4 LDA &03CA :\ block flag LSR A :\ A=A/2 bit 0 into carry to check for locked file BCC LF6BD :\ if not set then skip next instruction JMP LF1F6 :\ 'locked' file routine .LF6BD LDA &03DD :\ Expected BGET file block number lo STA &B4 :\ current block no. lo LDA &03DE :\ expected BGET file block number hi STA &B5 :\ current block no. hi LDA #&00 :\ A=0 .LF6C9 STA &B0 :\ current load address LDA #&0A :\ A=&A setting current load address to the CFS/RFS STA &B1 :\ current load address buffer at &A00 LDA #&FF :\ A=&FF to set other 2 bytes STA &B2 :\ current load address high word STA &B3 :\ current load address high word JSR LF7D5 :\ reset flags JSR LF9B4 :\ load file from tape BNE LF702 :\ if return non zero F702 else LDA &0AFF :\ get last character from input buffer STA &02ED :\ last character currently resident block JSR LFB69 :\ inc. current block no. STX &03DD :\ expected BGET file block number lo STY &03DE :\ expected BGET file block number hi LDX #&02 :\ X=2 .LF6EE LDA &03C8,X :\ read bytes from block flag/block length STA &02EA,X :\ store into current values of above DEX :\ X=X-1 BPL LF6EE :\ until X=-1 (&FF) BIT &02EC :\ block flag of currently resident block BPL LF6FF :\ JSR LF249 :\ print newline if needed .LF6FF JMP LFAF2 :\ enable second processor and reset serial system .LF702 JSR LF637 :\ search for a specified block BNE LF6B4 :\ if NE check for locked condition else .LF707 CMP #&2A :\ is it Synchronising byte &2A? BEQ LF742 :\ if so F742 CMP #&23 :\ else is it &23 (header substitute in ROM files) BNE LF71E :\ if not BAD ROM error INC &03C6 :\ block number BNE LF717 :\ INC &03C7 :\ block number hi .LF717 LDX #&FF :\ X=&FF BIT LD9B7 :\ to set V & M BNE LF773 :\ and jump (ALWAYS!!) to F773 .LF71E LDA #&F7 :\ clear bit 3 of RFS status (current CAT status) JSR LF33D :\ RFS status =RFS status AND A BRK :\ and cause error EQUB &D7 :\ error number EQUB &42 :\ F725 DB 'Bad Rom' ADC (&64,X) :\ JSR &4F52 :\ EOR &A000 :\ \********** pick up a header ******************************************** EQUB &FF :\ switch Motor on JSR LFB90 :\ LDA #&01 :\ A=1 STA &C2 :\ progress flag JSR LFB50 :\ control serial system .LF739 \confirm ESC not set and CFS not executing JSR LF995 :\ LDA #&03 :\ A=3 CMP &C2 :\ progress flag BNE LF739 :\ back until &C2=3 .LF742 \Y=0 LDY #&00 :\ JSR LFB7C :\ zero checksum bytes .LF747 \get character from file and do CRC JSR LF797 :\ BVC LF766 :\ if V clear on exit F766 STA &03B2,Y :\ else store BEQ LF757 :\ or if A=0 F757 INY :\ Y=Y+1 CPY #&0B :\ if Y<>&B BNE LF747 :\ go back for next character DEY :\ Y=Y-1 .LF757 \X=12 LDX #&0C :\ .LF759 \get character from file and do CRC JSR LF797 :\ BVC LF766 :\ if V clear on exit F766 STA &03B2,X :\ else store byte INX :\ X=X+1 CPX #&1F :\ if X<>31 BNE LF759 :\ goto F759 .LF766 \A=Y TYA :\ TAX :\ X=A LDA #&00 :\ A=0 STA &03B2,Y :\ store it LDA &BE :\ CRC workspace ORA &BF :\ CRC workspace STA &C1 :\ Checksum result .LF773 \set (BE/C0) to 0 JSR LFB78 :\ STY &C2 :\ progress flag TXA :\ A=X BNE LF7D4 :\ .LF77B \filing system flag 0=CFS 2=RFS LDA &0247 :\ BEQ LF72D :\ if cassette F72D .LF780 \read RFS data rom or Phrom JSR LEE51 :\ CMP #&2B :\ is it ROM file terminator? BNE LF707 :\ if not F707 \********* terminator found ********************************************** LDA #&08 :\ A=8 isolating bit 3 CAT status AND &E2 :\ CFS status byte BEQ LF790 :\ if clera skip next instruction JSR LF24D :\ print CR if CFS not operational .LF790 \get byte from data Rom JSR LEE18 :\ BCC LF780 :\ if carry set F780 CLV :\ clear overflow flag RTS :\ return \**************** get character from file and do CRC ******************* \ :\ \ filing system flag 0=CFS 2=RFS .LF797 LDA &0247 :\ BEQ LF7AD :\ if cassette F7AD TXA :\ A=X to save X and Y PHA :\ save X on stack TYA :\ A=Y PHA :\ save Y on stack JSR LEE51 :\ read RFS data rom or Phrom STA &BD :\ put it in temporary storage LDA #&FF :\ A=&FF STA &C0 :\ filing system buffer flag PLA :\ get back Y TAY :\ Y=A PLA :\ get back X TAX :\ X=A .LF7AD \check for Escape and loop till bit 7 of FS buffer JSR LF884 :\ :\ flag=1 \************************** perform CRC ********************************** .LF7B0 \save flags on stack PHP :\ PHA :\ save A on stack SEC :\ set carry flag ROR &CB :\ CRC Bit counter EOR &BF :\ CRC workspace STA &BF :\ CRC workspace .LF7B9 \CRC workspace LDA &BF :\ ROL A :\ A=A*2 C=bit 7 BCC LF7CA :\ ROR A :\ A=A/2 EOR #&08 :\ STA &BF :\ CRC workspace LDA &BE :\ CRC workspace EOR #&10 :\ STA &BE :\ CRC workspace SEC :\ set carry flag .LF7CA \CRC workspace ROL &BE :\ ROL &BF :\ CRC workspace LSR &CB :\ CRC Bit counter BNE LF7B9 :\ PLA :\ get back A PLP :\ get back flags .LF7D4 \return RTS :\ \ A=0 .LF7D5 LDA #&00 :\ .LF7D7 \&BD=character temporary storage buffer=0 STA &BD :\ LDX #&00 :\ X=0 STX &BC :\ file status or temporary store BVC LF7E9 :\ LDA &03C8 :\ block length ORA &03C9 :\ block length hi BEQ LF7E9 :\ if 0 F7E9 LDX #&04 :\ else X=4 .LF7E9 \filename length/progress flag STX &C2 :\ RTS :\ return \*************** SAVE A BLOCK ******************************************** \ save flags on stack .LF7EC PHP :\ LDX #&03 :\ X=3 LDA #&00 :\ A=0 .LF7F1 \clear 03CB/E (RFS EOF+1?) STA &03CB,X :\ DEX :\ X=X-1 BPL LF7F1 :\ LDA &03C6 :\ block number ORA &03C7 :\ block number hi BNE LF804 :\ if block =0 F804 else JSR LF892 :\ generate a 5 second delay BEQ LF807 :\ goto F807 .LF804 \generate delay set by interblock gap JSR LF896 :\ .LF807 \A=&2A LDA #&2A :\ STA &BD :\ store it in temporary file JSR LFB78 :\ set (BE/C0) to 0 JSR LFB4A :\ set ACIA control register JSR LF884 :\ check for Escape and loop till bit 7 of FS buffer :\ flag=1 DEY :\ Y=Y-1 .LF815 \Y=Y+1 INY :\ LDA &03D2,Y :\ move sought filename STA &03B2,Y :\ into filename block JSR LF875 :\ transfer byte to CFS and do CRC BNE LF815 :\ if filename not complet then do it again \****** deal with rest of header **************************************** LDX #&0C :\ X=12 .LF823 \get filename byte LDA &03B2,X :\ JSR LF875 :\ transfer byte to CFS and do CRC INX :\ X=X+1 CPX #&1D :\ until X=29 BNE LF823 :\ JSR LF87B :\ save checksum to TAPE reset buffer flag LDA &03C8 :\ block length ORA &03C9 :\ block length hi BEQ LF855 :\ if 0 F855 LDY #&00 :\ else Y=0 JSR LFB7C :\ zero checksum bytes .LF83E \get a data byte LDA (&B0),Y :\ JSR LFBD3 :\ check if second processor file test tube prescence BEQ LF848 :\ if not F848 else LDX LFEE5 :\ Tube FIFO3 .LF848 \A=X TXA :\ JSR LF875 :\ transfer byte to CFS and do CRC INY :\ Y=Y+1 CPY &03C8 :\ block length BNE LF83E :\ JSR LF87B :\ save checksum to TAPE reset buffer flag .LF855 \check for Escape and loop till bit 7 of FS buffer JSR LF884 :\ :\ flag=1 JSR LF884 :\ check for Escape and loop till bit 7 of FS buffer :\ flag=1 JSR LFB46 :\ reset ACIA LDA #&01 :\ A=1 JSR LF898 :\ generate 0.1 * A second delay PLP :\ get back flags JSR LF8B9 :\ update block flag, PRINT filename (& address if reqd) BIT &03CA :\ block flag BPL LF874 :\ is this last block (bit 7 set)? PHP :\ save flags on stack JSR LF892 :\ generate a 5 second delay JSR LF246 :\ sound bell and abort PLP :\ get back flags .LF874 \return RTS :\ \****************** transfer byte to CFS and do CRC ********************** \ :\ \ save byte to buffer, transfer to CFS & reset flag .LF875 JSR LF882 :\ JMP LF7B0 :\ perform CRC \***************** save checksum to TAPE reset buffer flag **************** \ CRC workspace .LF87B LDA &BF :\ JSR LF882 :\ save byte to buffer, transfer to CFS & reset flag LDA &BE :\ CRC workspace \************** save byte to buffer, transfer to CFS & reset flag ******** .LF882 \store A in temporary buffer STA &BD :\ \***** check for Escape and loop untill bit 7 of FS buffer flag=1 *********** .LF884 \confirm ESC not set and CFS not executing JSR LF995 :\ BIT &C0 :\ filing system buffer flag BPL LF884 :\ loop until bit 7 of &C0 is set LDA #&00 :\ A=0 STA &C0 :\ filing system buffer flag LDA &BD :\ get temporary store byte RTS :\ return \****************** generate a 5 second delay *************************** \ A=50 .LF892 LDA #&32 :\ BNE LF898 :\ generate delay 100ms *A (5 seconds) \*************** generate delay set by interblock gap ******************** .LF896 \get current interblock flag LDA &C7 :\ \*************** generate delay ****************************************** .LF898 \X=5 LDX #&05 :\ .LF89A \CFS timeout counter STA &0240 :\ .LF89D \confirm ESC not set and CFS not executing JSR LF995 :\ BIT &0240 :\ CFS timeout counter (decremented each 20ms) BPL LF89D :\ if +ve F89D DEX :\ X=X-1 BNE LF89A :\ RTS :\ return \************ generate screen reports *********************************** \ block number .LF8A9 LDA &03C6 :\ ORA &03C7 :\ block number hi BEQ LF8B6 :\ if 0 F8B6 BIT &03DF :\ copy of last read block flag BPL LF8B9 :\ update block flag, PRINT filename (& address if reqd) .LF8B6 \print newline if needed JSR LF249 :\ \************** update block flag, PRINT filename (& address if reqd) **** .LF8B9 \Y=0 LDY #&00 :\ STY &BA :\ current block flag LDA &03CA :\ block flag STA &03DF :\ copy of last read block flag JSR LE7DC :\ check if free to print message BEQ LF933 :\ if A=0 on return Cassette system is busy LDA #&0D :\ else A=&0D, carriage return JSR OSWRCH :\ print it (note no linefeed as it's via OSWRCH) .LF8CD \get byte from filename LDA &03B2,Y :\ BEQ LF8E2 :\ if 0 filename is ended CMP #&20 :\ if ; < = > ? CMP #&3A :\ if A< ASC() BCC LF98E :\ goto F98E ADC #&06 :\ else add 7 to convert ; < = > ? to A B C D E F .LF98E \print character and return JMP OSWRCH :\ \******************** print a space ************************************* \ A=' ' .LF991 LDA #&20 :\ BNE LF98E :\ goto F98E to print it \******************** confirm CFS not operating, nor ESCAPE flag set ***** .LF995 \save flags on stack PHP :\ BIT &EB :\ CFS Active flag BMI LF99E :\ BIT &FF :\ if ESCAPE condition BMI LF9A0 :\ goto F9A0 .LF99E \get back flags PLP :\ RTS :\ return \ close input file .LF9A0 JSR LF33B :\ JSR LFAF2 :\ enable second processor and reset serial system LDA #&7E :\ A=&7E (126) Acknowledge ESCAPE JSR OSBYTE :\ OSBYTE Call BRK :\ ORA (&45),Y :\ error 17 :\ EQUB &73 :\ EQUB &63 :\ ADC (&70,X) :\ ADC &00 :\ .LF9B4 \OS SERIES 10 \LAST PART \GEOFF COX \****************************** LOAD ************************************* TYA :\ A=Y BEQ LF9C4 :\ JSR LFA46 :\ print message following call ORA &6F4C :\ ADC (&64,X) :\ ADC #&6E :\ EQUB &67 :\ ORA &8500 :\ :\ TSX :\ current block flag LDX #&FF :\ X=&FF LDA &C1 :\ Checksum result BNE LF9D9 :\ if not 0 F9D9 JSR LFA72 :\ else check filename header block matches searched :\ filename if this returns NE then no match PHP :\ save flags on stack LDX #&FF :\ X=&FF LDY #&99 :\ Y=&99 LDA #&FA :\ A=&FA this set Y/A to point to 'File?' FA99 PLP :\ get back flags BNE LF9F5 :\ report a query unexpected file name .LF9D9 LDY #&8E :\ making Y/A point to 'Data' FA8E for CRC error LDA &C1 :\ Checksum result BEQ LF9E3 :\ if 0 F9E3 LDA #&FA :\ A=&FA BNE LF9F5 :\ jump to F9F5 .LF9E3 LDA &03C6 :\ block number CMP &B4 :\ current block no. lo BNE LF9F1 :\ if not eual F9F1 LDA &03C7 :\ block number hi CMP &B5 :\ current block no. hi BEQ LFA04 :\ if equal FA04 .LF9F1 LDY #&A4 :\ Y=&A4 LDA #&FA :\ A=&FA point to 'Block?' error unexpected block no. .LF9F5 :\ at this point an error HAS occurred PHA :\ save A on stack TYA :\ A=Y PHA :\ save Y on stack TXA :\ A=X PHA :\ save X on stack JSR LF8B6 :\ print CR if indicated by current block flag PLA :\ get back A TAX :\ X=A .LF9FF PLA :\ get back A TAY :\ Y=A PLA :\ get back A BNE LFA18 :\ jump to FA18 .LFA04 TXA :\ A=X PHA :\ save A on stack JSR LF8A9 :\ report JSR LFAD6 :\ check loading progress, read another byte PLA :\ get back A TAX :\ X=A LDA &BE :\ CRC workspace ORA &BF :\ CRC workspace BEQ LFA8D :\ LDY #&8E :\ Y=&8E LDA #&FA :\ A=&FA FA8E points to 'Data?' .LFA18 DEC &BA :\ current block flag PHA :\ save A on stack BIT &EB :\ CFS Active flag BMI LFA2C :\ if active FA2C TXA :\ A=X AND &0247 :\ filing system flag 0=CFS 2=RFS BNE LFA2C :\ TXA :\ A=X AND #&11 :\ AND &BB :\ current OPTions BEQ LFA3C :\ ignore errors .LFA2C PLA :\ get back A STA &B9 :\ store A on &B9 STY &B8 :\ store Y on &B8 JSR LF68B :\ do *EXEC 0 to tidy up LSR &EB :\ halve CFS Active flag to clear bit 7 JSR LFAE8 :\ bell, reset ACIA & motor JMP (&00B8) :\ display selected error report .LFA3C PLA :\ get back A INY :\ Y=Y+1 BNE LFA43 :\ CLC :\ clear carry flag ADC #&01 :\ Add 1 .LFA43 PHA :\ save A on stack TYA :\ A=Y PHA :\ save Y on stack .LFA46 JSR LE7DC :\ check if free to print message TAY :\ Y=A .LFA4A PLA :\ get back A STA &B8 :\ &B8=8 PLA :\ get back A STA &B9 :\ &B9=A TYA :\ A=Y PHP :\ save flags on stack .LFA52 INC &B8 :\ BNE LFA58 :\ INC &B9 :\ .LFA58 LDY #&00 :\ Y=0 LDA (&B8),Y :\ get byte BEQ LFA68 :\ if 0 Fa68 PLP :\ get back flags PHP :\ save flags on stack BEQ LFA52 :\ if 0 FA52 to get next character JSR OSASCI :\ else print JMP LFA52 :\ and do it again .LFA68 PLP :\ get back flags INC &B8 :\ increment pointers BNE LFA6F :\ INC &B9 :\ .LFA6F JMP (&00B8) :\ and print error message so no error condition .LFA72 :\ occcurs \************ compare filenames ****************************************** LDX #&FF :\ X=&FF inx will mean X=0 .LFA74 INX :\ X=X+1 LDA &03D2,X :\ sought filename byte BNE LFA81 :\ if not 0 FA81 TXA :\ else A=X BEQ LFA80 :\ if X=0 A=0 exit LDA &03B2,X :\ else A=filename byte .LFA80 RTS :\ return .LFA81 :\ JSR LE4E3 :\ set carry if byte in A is not upper case Alpha EOR &03B2,X :\ compare with filename BCS LFA8B :\ if carry set FA8B AND #&DF :\ else convert to upper case .LFA8B BEQ LFA74 :\ and if A=0 filename characters match so do it again .LFA8D RTS :\ return BRK :\ CLD :\ error number ORA &6144 :\ STZ &61,X :\ EQUB &3F :\ BRK :\ BNE LFAAE :\ BRK :\ EQUB &DB :\ error number ORA &6946 :\ JMP (&3F65) :\ BRK :\ BNE LFAAE :\ BRK :\ PHX :\ error number ORA &6C42 :\ FAA6 DB 'Block?' EQUB &6F :\ EQUB &63 :\ EQUB &6B :\ EQUB &3F :\ BRK :\ .LFAAE \current block flag LDA &BA :\ BEQ LFAD3 :\ if 0 FAD3 else TXA :\ A=X BEQ LFAD3 :\ If X=0 FAD3 LDA #&22 :\ A=&22 BIT &BB :\ current OPTions checking bits 1 and 5 BEQ LFAD3 :\ if neither set no retry so FAD3 else JSR LFB46 :\ reset ACIA TAY :\ Y=A JSR LFA4A :\ print following message ORA &5207 :\ Carriage RETURN :\ BEEP ADC &77 :\ two more newlines ADC #&6E :\ STZ &20 :\ STZ &61,X :\ BVS LFB34 :\ ORA &000D :\ .LFAD2 RTS :\ return .LFAD3 JSR LF24D :\ print CR if CFS not operational .LFAD6 LDA &C2 :\ filename length/progress flag BEQ LFAD2 :\ if 0 return else JSR LF995 :\ confirm ESC not set and CFS not executing LDA &0247 :\ filing system flag 0=CFS 2=RFS BEQ LFAD6 :\ if CFS FAD6 JSR LF588 :\ else set up ACIA etc JMP LFAD6 :\ and loop back again .LFAE8 \********** sound bell, reset ACIA, motor off **************************** JSR LE7DC :\ check if free to print message BEQ LFAF2 :\ enable second processor and reset serial system LDA #&07 :\ beep JSR OSWRCH :\ .LFAF2 LDA #&80 :\ JSR LFBBD :\ enable 2nd proc. if present and set up osfile block LDX #&00 :\ JSR LFB95 :\ switch on motor .LFAFC PHP :\ save flags on stack SEI :\ prevent IRQ interrupts LDA &0282 :\ get serial ULA control register setting STA LFE10 :\ write to serial ULA control register setting LDA #&00 :\ A=0 STA &EA :\ store A RS423 timeout counter BEQ LFB0B :\ jump FB0B .LFB0A PHP :\ save flags on stacksave flags .LFB0B JSR LFB46 :\ release ACIA (by &FE08=3) LDA &0250 :\ get last setting of ACIA JMP LE189 :\ set ACIA and &250 from A before exit .LFB14 PLP :\ get back flags BIT &FF :\ if bit 7of ESCAPE flag not set BPL LFB31 :\ then FB31 RTS :\ else return as unserviced ESCAPE is pending .LFB1A \************************************************************************* \* * \* Claim serial system for sequential Access * \* * \************************************************************************* LDA &E3 :\ get cassette filing system options byte :\ high nybble used for LOAD & SAVE operations :\ low nybble used for sequential access :\ 0000 Ignore errors, no messages :\ 0001 Abort if error, no messages :\ 0010 Retry after error, no messages :\ 1000 Ignore error short messages :\ 1001 Abort if error short messages :\ 1010 Retry after error short messages :\ 1100 Ignore error long messages :\ 1101 Abort if error long messages :\ 1110 Retry after error long messages ASL A :\ move low nybble into high nybble ASL A :\ ASL A :\ ASL A :\ STA &BB :\ current OPTions save into &BB LDA &03D1 :\ get sequential block gap BNE LFB2F :\ goto to &FB2F .LFB27 \************************************************************************* \* * \* claim serial system for cassette etc. * \* * \************************************************************************* LDA &E3 :\ get cassette filing system options byte :\ high nybble used for LOAD & SAVE operations :\ low nybble used for sequential access :\ 0000 Ignore errors, no messages :\ 0001 Abort if error, no messages :\ 0010 Retry after error, no messages :\ 1000 Ignore error short messages :\ 1001 Abort if error short messages :\ 1010 Retry after error short messages :\ 1100 Ignore error long messages :\ 1101 Abort if error long messages :\ 1110 Retry after error long messages AND #&F0 :\ clear low nybble STA &BB :\ as current OPTions LDA #&06 :\ set current interblock gap .LFB2F STA &C7 :\ to 6 .LFB31 CLI :\ allow interrupts PHP :\ save flags on stack SEI :\ prevent interrupts .LFB34 BIT &024F :\ check if RS423 is busy BPL LFB14 :\ if not FB14 LDA &EA :\ see if RS423 has timed out BMI LFB14 :\ if not FB14 LDA #&01 :\ else load RS423 timeout counter with STA &EA :\ 1 to indicate that cassette has 6850 JSR LFB46 :\ reset ACIA with &FE80=3 PLP :\ get back flags RTS :\ return .LFB46 LDA #&03 :\ A=3 BNE LFB65 :\ and exit after resetting ACIA .LFB4A \********************** set ACIA control register ********************** LDA #&30 :\ set current ACIA control register STA &CA :\ to &30 BNE LFB63 :\ and goto FB63 .LFB50 :\ if bit 7=0 motor off 1=motor on \***************** control cassette system ******************************* LDA #&05 :\ set &FE10 to 5 STA LFE10 :\ setting a transmit baud rate of 300,motor off LDX #&FF :\ .LFB57 DEX :\ delay loop BNE LFB57 :\ STX &CA :\ &CA=0 LDA #&85 :\ Turn motor on and keep baud rate at 300 recieve STA LFE10 :\ 19200 transmit LDA #&D0 :\ A=&D0 .LFB63 ORA &C6 :\ .LFB65 STA LFE08 :\ set up ACIA control register RTS :\ returnand return .LFB69 LDX &03C6 :\ block number LDY &03C7 :\ block number hi INX :\ X=X+1 STX &B4 :\ current block no. lo BNE LFB75 :\ INY :\ Y=Y+1 .LFB75 STY &B5 :\ current block no. hi RTS :\ return .LFB78 LDY #&00 :\ STY &C0 :\ filing system buffer flag .LFB7C \*****************set (zero) checksum bytes ****************************** STY &BE :\ CRC workspace STY &BF :\ CRC workspace RTS :\ return .LFB81 \*********** copy sought filename routine ******************************** LDY #&FF :\ Y=&FF .LFB83 INY :\ Y=Y+1 INX :\ X=X+1 LDA &0300,X :\ STA &03D2,Y :\ sought filename BNE LFB83 :\ until end of filename (0) RTS :\ return .LFB8E LDY #&00 :\ Y=0 .LFB90 \********************** switch Motor on ********************************** CLI :\ allow IRQ interrupts LDX #&01 :\ X=1 STY &C3 :\ store Y as current file handle .LFB95 \******************** control motor ************************************ LDA #&89 :\ do osbyte 137 LDY &C3 :\ get back file handle (preserved thru osbyte) JMP OSBYTE :\ turn on motor .LFB9C \****************** confirm file is open ******************************** STA &BC :\ file status or temporary store TYA :\ A=Y EOR &0247 :\ filing system flag 0=CFS 2=RFS TAY :\ Y=A LDA &E2 :\ CFS status byte AND &BC :\ file status or temporary store LSR A :\ A=A/2 DEY :\ Y=Y-1 BEQ LFBAF :\ LSR A :\ A=A/2 DEY :\ Y=Y-1 BNE LFBB1 :\ .LFBAF BCS LFBFE :\ .LFBB1 BRK :\ DEC &6843,X :\ error number ADC (&6E,X) :\ ROR &6C65 :\ BRK :\ \************* read from second processor ******************************** .LFBBB \A=1 LDA #&01 :\ .LFBBD \check if second processor file test tube prescence JSR LFBD3 :\ BEQ LFBFE :\ if not exit TXA :\ A=X LDX #&B0 :\ current load address LDY #&00 :\ Y=00 .LFBC7 \save A on stack PHA :\ LDA #&C0 :\ filing system buffer flag .LFBCA \and out to TUBE JSR &0406 :\ BCC LFBCA :\ PLA :\ get back A JMP &0406 :\ \*************** check if second processor file test tube prescence ****** \ X=A .LFBD3 TAX :\ LDA &B2 :\ current load address high word AND &B3 :\ current load address high word CMP #&FF :\ BEQ LFBE1 :\ if &FF then its for base processor LDA &027A :\ &FF if tube present AND #&80 :\ to set bit 7 alone .LFBE1 \return RTS :\ \******** control ACIA and Motor ***************************************** \ A=&85 .LFBE2 LDA #&85 :\ STA LFE10 :\ write to serial ULA control register setting JSR LFB46 :\ reset ACIA LDA #&10 :\ A=16 JSR LFB63 :\ set ACIA to CFS baud rate .LFBEF \confirm ESC not set and CFS not executing JSR LF995 :\ LDA LFE08 :\ read ACIA status register AND #&02 :\ clear all but bit 1 BEQ LFBEF :\ if clear FBEF LDA #&AA :\ else A=&AA STA LFE09 :\ transmit data register .LFBFE \return RTS :\ BRK :\ \************** FRED 1MHz Bus memory-mapped I/O ************************** .LFC00 \test hardware PLP :\ EQUB &43 :\ teletext AND #&20 :\ AND (&39),Y :\ SEC :\ AND (&20),Y :\ EOR (&63,X) :\ EQUB &6F :\ ADC (&6E) :\ JSR &6F43 :\ ADC &7570 :\ Prestel STZ &65,X :\ ADC (&73) :\ IEEE interface JSR &744C :\ STZ &2E :\ EQUB &54 :\ PLA :\ ADC (&6E,X) :\ EQUB &6B :\ EQUB &73 :\ JSR &7261 :\ ADC &20 :\ STZ &75 :\ ADC &20 :\ STZ &6F,X :\ JSR &6874 :\ ADC &20 :\ winchester disc interface ROR &6F :\ JMP (&6F6C) :\ EQUB &77 :\ ADC #&6E :\ EQUB &67 :\ JSR &6F63 :\ ROR &7274 :\ ADC #&62 :\ ADC &74,X :\ EQUB &6F :\ ADC (&73) :\ JSR &6F74 :\ JSR &6874 :\ ADC &20 :\ STZ &65 :\ ROR &65,X :\ JMP (&706F) :\ ADC &6E65 :\ STZ &20,X :\ EQUB &6F :\ ROR &20 :\ STZ &68,X :\ ADC &20 :\ EQUB &42 :\ EQUB &42 :\ EQUB &43 :\ JSR &6F43 :\ ADC &7570 :\ STZ &65,X :\ ADC (&20) :\ PLP :\ ADC (&6D,X) :\ EQUB &6F :\ ROR &2067 :\ EQUB &6F :\ STZ &68,X :\ ADC &72 :\ EQUB &73 :\ JSR &6F74 :\ EQUB &6F :\ JSR &756E :\ ADC &7265 :\ EQUB &6F :\ ADC &73,X :\ JSR &6F74 :\ JSR &656D :\ ROR &6974 :\ EQUB &6F :\ ROR &3A29 :\ AND &4420 :\ ADC (&76,X) :\ ADC #&64 :\ JSR &6C41 :\ JMP (&6E65) :\ BIT &6F42 :\ EQUB &62 :\ JSR &7541 :\ EQUB &73 :\ STZ &69,X :\ ROR &522C :\ ADC (&6D,X) :\ JSR &6142 :\ ROR &7265 :\ ROR A :\ ADC &65 :\ BIT &6150 :\ ADC &6C,X :\ JSR &6F42 :\ ROR &2C64 :\ EOR (&6C,X) :\ JMP (&6E65) :\ JSR &6F42 :\ EQUB &6F :\ STZ &68,X :\ ADC (&6F) :\ ADC &2C64,Y :\ EQUB &43 :\ ADC (&6D,X) :\ EQUB &62 :\ ADC (&69) :\ STZ &67 :\ ADC &2C :\ EQUB &43 :\ JMP (&6165) :\ ADC (&74) :\ EQUB &6F :\ ROR &2C65 :\ LSR A :\ EQUB &6F :\ PLA :\ ROR &4320 :\ EQUB &6F :\ paging register for JIM expansion memory JMP (&2C6C) :\ LSR A :\ EQUB &6F :\ PLA :\ ROR &4320 :\ EQUB &6F :\ SEI :\ BIT &6E41 :\ \************** JIM 1MHz Bus memory-expansion page *********************** STZ &79 :\ Ecosoak Vector JSR &7243 :\ ADC #&70 :\ BVS LFD7D :\ BIT &6843 :\ ADC (&69) :\ EQUB &73 :\ JSR &7543 :\ ADC (&72) :\ ADC &362C,Y :\ AND &30,X :\ AND (&20) :\ STZ &65 :\ EQUB &73 :\ ADC #&67 :\ ROR &7265 :\ EQUB &73 :\ BIT &654A :\ ADC (&65) :\ ADC &2079 :\ EQUB &44 :\ ADC #&6F :\ ROR &542C :\ ADC #&6D :\ JSR &6F44 :\ EQUB &62 :\ EQUB &73 :\ EQUB &6F :\ ROR &4A2C :\ EQUB &6F :\ ADC &20 :\ EQUB &44 :\ ADC &6E,X :\ ROR &502C :\ ADC (&75,X) :\ JMP (&4620) :\ ADC (&72,X) :\ ADC (&65) :\ JMP (&2C6C) :\ LSR &65 :\ ADC (&72) :\ ADC (&6E,X) :\ STZ &69,X :\ BIT &7453 :\ ADC &76 :\ ADC &20 :\ LSR &75 :\ ADC (&62) :\ ADC &72 :\ BIT &6F4A :\ ROR &4720 :\ ADC #&62 :\ EQUB &62 :\ EQUB &6F :\ ROR &2C73 :\ EOR (&6E,X) :\ STZ &72 :\ ADC &77 :\ JSR &6F47 :\ ADC (&64) :\ EQUB &6F :\ ROR &4C2C :\ ADC (&77,X) :\ ADC (&65) :\ ROR &6563 :\ JSR &6148 :\ ADC (&64) :\ EQUB &77 :\ ADC #&63 :\ EQUB &6B :\ BIT &7944 :\ JMP (&6E61) :\ JSR &6148 :\ ADC (&72) :\ ADC #&73 :\ BIT &6548 :\ ADC (&6D) :\ ADC (&6E,X) :\ ROR &4820 :\ ADC (&75,X) :\ EQUB &73 :\ ADC &72 :\ BIT &6948 :\ STZ &61,X :\ EQUB &63 :\ PLA :\ ADC #&2C :\ EOR (&6E,X) :\ STZ &79 :\ JSR &6F48 :\ BVS LFE32 :\ ADC &72 :\ BIT &4349 :\ JMP &4D2C :\ ADC (&72,X) :\ STZ &69,X :\ ROR &4A20 :\ ADC (&63,X) :\ EQUB &6B :\ EQUB &73 :\ EQUB &6F :\ ROR &422C :\ ADC (&69) :\ ADC (&6E,X) :\ JSR &6F4A :\ ROR &7365 :\ BIT &6843 :\ ADC (&69) :\ EQUB &73 :\ JSR &6F4A :\ ADC (&64) :\ ADC (&6E,X) :\ BIT &6144 :\ ROR &69,X :\ STZ &20 :\ EQUB &4B :\ ADC #&6E :\ EQUB &67 :\ BIT &6144 :\ ROR &69,X :\ \************** SHEILA MOS memory-mapped I/O *************************** \ :\ DEVICE WRITE READ .LFE00 \ 6845 CRTC address register EQUB 0:EQUB &20 :\ :\ 6845 CRTC data register EQUB &4B :\ Border colour border colour ADC #&74 :\ EQUB &73 :\ EQUB &6F :\ ROR &502C :\ ADC (&75,X) :\ JMP (&4B20) :\ ADC (&69) :\ EQUB &77 :\ ADC (&63,X) :\ PLY :\ ADC &6B :\ BIT &6F43 :\ ADC &7570 :\ STZ &65,X :\ ADC (&20) :\ .LFE21 JMP &6261 :\ Video ULA palette register palette register EQUB &6F :\ ADC (&61) :\ STZ &6F,X :\ ADC (&79) :\ BIT &6550 :\ STZ &65,X :\ .LFE30 ADC (&20) :\ ROM latch paged ROM ID write only .LFE32 EOR &6C69 :\ JMP (&7265) :\ BIT &7241 :\ STZ &68,X :\ ADC &72,X :\ JSR &6F4E :\ .LFE42 ADC (&6D) :\ MOS 6522 VIA data direction register B ADC (&6E,X) :\ MOS 6522 VIA T1C-L latches T1 low Order counter .LFE46 BIT &6C47 :\ MOS 6522 VIA T1L-L low order latches .LFE49 ADC &206E,Y :\ MOS 6522 VIA T2C-H T2 high order counter .LFE4C BVC LFEB6 :\ MOS 6522 VIA Peripheral control register PCR .LFE4E ADC #&6C :\ MOS 6522 VIA Interrupt enable register IER JMP (&7069) :\ EQUB &73 :\ BIT &694D :\ EQUB &6B :\ ADC &20 :\ BVC LFECE :\ ADC &65 :\ EQUB &73 :\ BIT &6F4A :\ PLA :\ USER 6522 VIA data direction register B .LFE63 ROR &5220 :\ USER 6522 VIA data direction register A ADC (&64,X) :\ USER 6522 VIA T1L-L low order latches EQUB &63 :\ USER 6522 VIA T2C-L latches T2C-L lo order counter JMP (&6669) :\ USER 6522 VIA T2C-H T2 high order counter .LFE6C ROR &65 :\ USER 6522 VIA Peripheral control register PCR .LFE6E BIT &6957 :\ USER 6522 VIA Interrupt enable register IER JMP (&6562) :\ ADC (&66) :\ EQUB &6F :\ ADC (&63) :\ ADC &20 :\ EOR (&6F) :\ ADC (&64,X) :\ BIT &6550 :\ STZ &65,X :\ 8271 FDC reset register ADC (&20) :\ 8271 FDC data data EOR (&6F) :\ EQUB &62 :\ ADC #&6E :\ EQUB &73 :\ EQUB &6F :\ ROR &522C :\ ADC #&63 :\ PLA :\ ADC (&72,X) :\ STZ &20 :\ EOR (&75) :\ EQUB &73 :\ EQUB &73 :\ ADC &6C :\ JMP (&4B2C) :\ ADC #&6D :\ 68B54 ADLC control register 1 status register 1 JSR &7053 :\ 68B54 ADLC Tx FIFO (frame continue) Rx FIFO ADC &6E :\ EQUB &63 :\ ADC &2D :\ LSR A :\ EQUB &6F :\ ROR &7365 :\ BIT &7247 :\ ADC (&68,X) :\ ADC (&6D,X) :\ .LFEB6 JSR &6554 :\ EQUB &62 :\ EQUB &62 :\ ADC &4A2C,Y :\ EQUB &6F :\ ROR &5420 :\ .LFEC2 PLA :\ 7002 ADC lo data byte ADC (&63,X) :\ EQUB &6B :\ ADC (&61) :\ ADC &432C,Y :\ PLA :\ ADC (&69) :\ .LFECE EQUB &73 :\ JSR &7554 :\ ADC (&6E) :\ ADC &72 :\ BIT &6441 :\ ADC (&69) :\ ADC (&6E,X) :\ JSR &6157 :\ .LFEE0 ADC (&6E) :\ TUBE FIFO1 status register ADC &72 :\ TUBE FIFO2 status register BIT &6F52 :\ TUBE FIFO3 status register EQUB &67 :\ TUBE FIFO4 ADC &72 :\ JSR &6957 :\ JMP (&6F73) :\ ROR &412C :\ JMP (&6E61) :\ JSR &7257 :\ ADC #&67 :\ PLA :\ STZ &2E,X :\ CMP &20D9 :\ \********** EXTENDED VECTOR ENTRY POINTS********************************** \vectors are pointed to &F000 +vector No. vectors may then be directed thru \a three byte vector table whose XY address is given by osbyte A8, X=0, Y=&FF \this is set up as lo-hi byte in ROM and ROM number EOR (&FF),Y :\ XBRKV JSR LFF51 :\ JSR LFF51 :\ XIRQ1V JSR LFF51 :\ XIRQ2V JSR LFF51 :\ XCLIV JSR LFF51 :\ XBYTEV JSR LFF51 :\ XWORDV JSR LFF51 :\ XWRCHV JSR LFF51 :\ XRDCHV JSR LFF51 :\ XFILEV JSR LFF51 :\ XARGSV JSR LFF51 :\ XBGETV JSR LFF51 :\ XBPUTV JSR LFF51 :\ XGBPBV JSR LFF51 :\ XFINDV JSR LFF51 :\ XFSCV JSR LFF51 :\ XEVENTV JSR LFF51 :\ XUPTV JSR LFF51 :\ XNETV JSR LFF51 :\ XVDUV JSR LFF51 :\ XKEYV JSR LFF51 :\ XINSV JSR LFF51 :\ XREMV JSR LFF51 :\ XCNPV JSR LFF51 :\ XIND1V JSR LFF51 :\ XIND2V JSR LFF51 :\ XIND3V \at this point the stack will hold 4 bytes (at least) \S 0,1 extended vector address \S 2,3 address of calling routine \A,X,Y,P will be as at entry .LFF51 \save A on stack PHA :\ PHA :\ save A on stack PHA :\ save A on stack PHA :\ save A on stack PHA :\ save A on stack PHP :\ save flags on stack PHA :\ save A on stack TXA :\ A=X PHA :\ save X on stack TYA :\ A=Y PHA :\ save Y on stack TSX :\ get stack pointer into X (&F2 or less) LDA #&FF :\ A=&FF STA &0108,X :\ A LDA #&88 :\ STA &0107,X :\ LDY &010A,X :\ this is VECTOR number*3+2!! LDA &0D9D,Y :\ lo byte of action address STA &0105,X :\ store it on stack LDA &0D9E,Y :\ get hi byte STA &0106,X :\ store it on stack :\ at this point stack has YXAP and action address :\ followed by return address and 5 more bytes LDA &F4 :\ STA &0109,X :\ store original ROM number below this LDA &0D9F,Y :\ get new ROM number STA &F4 :\ store it as ram copy STA LFE30 :\ and switch to that ROM PLA :\ get back A TAY :\ Y=A PLA :\ get back A TAX :\ X=A PLA :\ get back A RTI :\ get back flags and jump to ROM vectored entry :\ leaving return address and 5 more bytes on stack \************ return address from ROM indirection ************************ \at this point stack comprises original ROM number,return from JSR &FF51, \return from original call the return from FF51 is garbage so; \ save flags on stack PHP :\ PHA :\ save A on stack TXA :\ A=X PHA :\ save X on stack TSX :\ (&F7 or less) LDA &0102,X :\ STORE A AND P OVER STA &0105,X :\ return address from (JSR &FF51) LDA &0103,X :\ hiding garbage by duplicating A and X just saved STA &0106,X :\ :\ now we have :\ flags, :\ A, :\ X, :\ ROM number, :\ A, :\ flags, :\ and original return address on stack :\ so PLA :\ get back X TAX :\ X=A PLA :\ get back A lose next two bytes PLA :\ get back A lose PLA :\ get back A ROM number STA &F4 :\ store it STA LFE30 :\ and set it PLA :\ get back A PLP :\ get back flags RTS :\ return and exit pulling original return address :\ from stack \FFA6 is also default input for CFS OSBPGB, VDUV, IND1V,IND2V,IND3V \as these functions are not implemented by the OS but may be used \by software or other filing systems or ROMs \************************************************************************* \* * \* OSBYTE &9D FAST BPUT * \* * \************************************************************************* \ A=X TXA :\ BCS OSBPUT :\ carry always set, jump to BPUT \************************************************************************* \* * \* OSBYTE &92 READ A BYTE FROM FRED * \* * \************************************************************************* :\ LDY LFC00,X :\ read a byte from FRED area RTS :\ return \************************************************************************* \* * \* OSBYTE &94 READ A BYTE FROM JIM * \* * \************************************************************************* :\ :\ \ read a byte from JIM area LDY LFD00,X :\ RTS :\ return \************************************************************************* \* * \* OSBYTE &96 READ A BYTE FROM SHEILA * \* * \************************************************************************* :\ :\ \ read a byte from SHEILA memory mapped I/O area LDY LFE00,X :\ RTS :\ return \*********** DEFAULT VECTOR TABLE **************************************** \ length of look up table in bytes EQUB &36:EQUW LD940 \************************************************************************** \************************************************************************** \** ** \** OPERATING SYSTEM FUNCTION CALLS ** \** ** \************************************************************************** \************************************************************************** JMP LDC0B JMP LC4C0 :\ VDUCHR VDU character output JMP LE494 :\ OSEVEN generate an EVENT JMP LEA1E :\ GSINIT initialise OS string JMP LEA2F :\ GSREAD read character from input stream JMP LDEC5 :\ NVRDCH non vectored OSRDCH JMP LE0A4 :\ NVWRCH non vectored OSWRCH \ Filing system entry points \ -------------------------- .OSFIND :\ &FFCE : JMP (findv) :\ Open or close a file .OSGBPB :\ &FFD1 : JMP (gbpbv) :\ Read/Write data from/to open file .OSBPUT :\ &FFD4 : JMP (bputv) :\ Put byte to open file .OSBGET :\ &FFD7 : JMP (bgetv) :\ Get byte from open file .OSARGS :\ &FFDA : JMP (argsv) :\ Read/Write open file information .OSFILE :\ &FFDD : JMP (filev) :\ Load/Save whole file : \ MOS I/O entry points \ -------------------- .OSRDCH :\ &FFE0 : JMP (rdchv) :\ Wait for character from input stream .OSASCI :\ &FFE3 : CMP #&0D:BNE OSWRCH :\ Write ASCII character .OSNEWL :\ &FFE7 : LDA #&0A:JSR OSWRCH :\ Write NEWLINE sequence .OSWRCR :\ &FFEC : LDA #&0D :\ Write CR character .OSWRCH :\ &FFEE : JMP (wrchv) :\ Write character to output stream .OSWORD :\ &FFF1 : JMP (wordv) :\ System function with control block .OSBYTE :\ &FFF4 : JMP (bytev) :\ System function with registers .OS_CLI :\ &FFF7 : JMP (cliv) :\ Pass command to command interpreter : .NMIV :\ &FFFA : EQUW &0D00 :\ NMI vector .RESETV :\ &FFFC : EQUW LD9CD :\ RESET vector .IRQV :\ &FFFE : EQUW LDC1C :\ IRQ/BRK vector ]:NEXT OSCLI"Save "+name$+" "+STR$~mcode%+" "+STR$~O%+" "+STR$~load%+" "+STR$~load% ON ERROR ON ERROR OFF:END *Quit : DEFFNif(A%):IFA%:z%=-1:=opt% ELSE z%=P%:=opt% DEFFNendif:IFz%=-1:=opt% ELSE z%=P%-z%:P%=P%-z%:O%=O%-z%:=opt%