diff --git a/drivers/console/README.md b/drivers/console/README.md new file mode 100644 index 0000000..c22f156 --- /dev/null +++ b/drivers/console/README.md @@ -0,0 +1,3 @@ +# Apple /// console driver + +This is updated from the original source code for the console driver v1.3.1 diff --git a/drivers/console/console.s b/drivers/console/console.s new file mode 100644 index 0000000..cd6e3ce --- /dev/null +++ b/drivers/console/console.s @@ -0,0 +1,3053 @@ +; .TITLE "SOS Console Driver" +; .NOPATCHLIST +; .NOMACROLIST +; +;----------------------------------------------------------------------- +; +; SOS Console Driver +; +; Copyright (C) 1983 by Apple Computer Inc. +; All Rights Reserved +; +; Previous Copyright (C) 1980, 1981 +; +; +; Revisions: +; +; 1.00 14-Nov-80 Initial Release +; +; 1.12 23-Sep-81 +; Bug fixes: +; Download 1-8 characters. +; Download entire character set. +; Include saved screen state in console state table. +; Adjust all pointers for proper extended addressing. +; Fix SYNC to monitor positive edge of vertical blanking. +; Delete extraneous data returned by status calls 12, 13, & 14. +; Fix erase option of character and line delete. +; Extensions: +; Add video toggle on control-5. +; Add dump & restore contents of viewport. +; Change keyboard transform table to include alpha-lock data. +; Retain cursor on SYNC. +; +; 1.30 11-Jan-83 +; Bug fixes: +; Wait for pending download on close. +; Fix branch in 40 column horizontal shift right. +; Fix cursor in dump & restore contents of viewport. +; Disable interrupts while setting events and screen mode. +; Extensions: +; Turn on video iff buffer is empty. +; Set bit 7 on control characters read from screen +; (applies to char copy and screen read status). +; Don't dump viewport when displaying control characters. +; Add status request 9, read screen with normal/inverse flag. +; 1.31 17-Mar-83 +; Fix VERIFY to eleminate noise when setting screen switches. +; +;----------------------------------------------------------------------- +; +; updated source for ca65 assembler +; - add $ for hex numbers +; - update local labels from $ to @ +; - some tweaks for high/low byte +; - ASCII to byte +; - update macro +; - EQU to = +; - BLOCK to RES +; + .feature labels_without_colons + .setcpu "6502" + .reloc + + +DEVTYPE = $61 +SUBTYPE = $01 +APPLE = $0001 +RELEASE = $1310 +; .PAGE +;----------------------------------------------------------------------- +; +; The macro SWITCH performs an N way branch based on a switch index. The +; maximum value of the switch index is 127 with bounds checking provided +; as an option. The macro uses the A and Y registers and alters the C, +; Z, and N flags of the status register, but the X register is unchanged. +; +; SWITCH [index], [bounds], adrs_table, [*] +; +; index This is the variable that is to be used as the switch index. +; If omitted, the value in the accumulator is used. +; +; bounds This is the maximum allowable value for index. If index +; exceeds this value, the carry bit will be set and execution +; will continue following the macro. If bounds is omitted, +; no bounds checking will be performed. +; +; adrs_table This is a table of addresses (low byte first) used by the +; switch. The first entry corresponds to index zero. +; +; * If an asterisk is supplied as the fourth parameter, the +; macro will push the switch address but will not exit to +; it; execution will continue following the macro. The +; program may then load registers or set the status before +; exiting to the switch address. +; +;----------------------------------------------------------------------- +; +; .MACRO SWITCH +; .IF "%1" <> "" ;If PARM1 is present, +; LDA %1 ; Load A with switch index +; .ENDC +; .IF "%2" <> "" ;If PARM2 is present, +; CMP #%2+1 ; Perform bounds checking +; BCS $3579 ; on switch index +; .ENDC +; ASL A +; TAY +; LDA %3+1,Y ;Get switch address from table +; PHA ; and push onto stack +; LDA %3,Y +; PHA +; .IF "%4" <> "*" ;If PARM4 is omitted, +; RTS ; Exit to code +; .ENDC ;Otherwise, drop through +; .IF "%2" <> "" +;$3579 +; .ENDC +; .ENDM + + .MACRO SWITCH index,bounds,adrs_table,noexec ;See SOS Reference + .IFNBLANK index ;If PARM1 is present, + LDA index ; load A with switch index + .ENDIF + .IFNBLANK bounds ;If PARM2 is present, + CMP #bounds+1 ; perform bounds checking + BCS @110 ; on switch index + .ENDIF + ASL A ;Multiply by 2 for table index + TAY + LDA adrs_table+1,Y ;Get switch address from table + PHA ; and push onto Stack + LDA adrs_table,Y + PHA + .IFBLANK noexec + ; .IF noexec <> '*' ;If PARM4 is omitted, + RTS ; exit to code + ; .ENDIF + .ENDIF +@110 + .ENDMACRO + + + .PROC CONSOLE + + .SEGMENT "TEXT" + .WORD $FFFF + .WORD 59 + .BYTE "Console Driver -- " + .BYTE "Copyright (C) 1983 by Apple Computer Inc." + + + .SEGMENT "DATA" +;---------------------------------------------------------------------- +; +; Device Handler Identification RES +; +;---------------------------------------------------------------------- +; +IDBLK .WORD 0000 ;Link to next device handler + .WORD CNSLDH ;Entry point address + .BYTE 8 ;Length of device name + .BYTE ".CONSOLE " + .BYTE $80,$00,$00 ;Device, Slot & Unit numbers + .BYTE DEVTYPE + .BYTE SUBTYPE + .BYTE 00 + .WORD 0000 + .WORD APPLE + .WORD RELEASE + .WORD 00 ;No configuration RES +; .PAGE +;---------------------------------------------------------------------- +; +; Global Data: +; +; SUSPFLSH: Suspend and Flush Output Flags +; 7 => Suspend Output +; 6 => Flush Output +; +; SCRNMODE: Current Screen Mode +; 7 => Off / On +; 6 => Text / Graphics +; 2 => Page 1 / Page 2 +; 1 => 40 Col / 80 Col +; 0 => B & W / Color +; +; +; State Flags: +; +; HMODE: Hardware Mode +; 7 => 40 Col / 80 Col +; 1 => 40 Col / 80 Col +; 0 => B & W / Color +; +; SMODE: Software Mode +; 5 => Normal / Inverse +; 4 => Disable / Enable Cursor +; 3 => Disable / Enable Scroll +; 2 => Disable / Enable Auto Carriage Return +; 1 => Disable / Enable Auto Line Feed +; 0 => Disable / Enable Auto Advance +; +; +; Permanant Zero Page Data: +; +; BASE1, BASE2: Screen Memory Pointers +; The base pointers point to the beginning of the current line. In +; 40 column mode, BASE1 points to the ASCII data while BASE2 points +; to the color information. In 80 column mode, BASE1 points to col- +; umn 0 of the viewport while BASE2 points to column 1. +; +; +; Temporary Zero Page Data: +; +; WORK1, WORK2: +; These pointers are used in conjunction with BASE1 and BASE2 for +; scrolling, shifting, etc. +; +; COUNT: +; Number of bytes read or written. +; +; ONEBYTE: +; Boolean flag for single byte read requests. +; +; BLANK: +; Holds an ASCII space in the current video mode (normal or inverse) +; for use in clearing the viewport. +; +; TEMPX: +; Temporary storage for X. +; +; FLAGS: +; Miscellaneous flags for use by SCROLL, SHIFT, SCRNDUMP, etc. +; +; TEMP1, TEMP2, TEMP3, TEMP4: +; General temporary storage for use by SCROLL, SHIFT, SCRNDUMP, etc. + +; .PAGE +; +; SOS Global Data & Subroutines +; +SUSPFLSH = $1902 ;Suspend & Flush flags +SCRNMODE = $1906 ;Current Screen Mode +ALLOCSIR = $1913 +DEALCSIR = $1916 +QUEEVENT = $191F +SYSERR = $1928 +; +; SOS Error Codes +; +XREQCODE = $20 ;Invalid request code +XCTLCODE = $21 ;Invalid controlstatus code +XCTLPARM = $22 ;Invalid controlstatus parm +XNOTOPEN = $23 ;Device not open +XNOTAVIL = $24 ;Device not available +XNORESRC = $25 ;Unable to obtain resource +; +; Hardware I/O Addresses +; +KAPORT = $C000 +KBPORT = $C008 +KYBDSTRB = $C010 +KYBDCLR = $01 ;Clear keyboard interrupt flag +KYBDDSBL = $01 ;Disable keyboard interrupts +KYBDENBL = $81 ;Enable keyboard interrupts +BELL = $C040 +VMODE0 = $C050 ;Video mode switches +VMODE1 = $C052 +VMODE2 = $C054 +VMODE3 = $C056 +SCRLDSBL = $C0D8 ;Disable graphics scroll +DNLDDSBL = $C0DA ;Disable character download +DNLDENBL = $C0DB ;Enable character download +VBLCLR = $18 ;Clear both VBL interrupt flags +VBLDSBL = $18 ;Disable both VBL interrupts +VBLENBL = $90 ;Enable VBL interrupt on CB2 +E_REG = $FFDF ;Environment register +E_IORB = $FFE0 ;6522 input/output register B +E_PCR = $FFEC ;6522 peripheral control register +E_IFR = $FFED ;6522 interrupt flag register +E_IER = $FFEE ;6522 interrupt mask register +B_REG = $FFEF ;Bank register +; +; ASCII Equates and Special Keys +; +ASC_NUL = $00 ;Null +ASC_SOH = $01 ;Start of Header +ASC_STX = $02 ;Start of Text +ASC_ETX = $03 ;End of Text +ASC_ENQ = $05 ;Enquiry +ASC_ACK = $06 ;Acknowledgement +ASC_BS = $08 ;Backspace +ASC_HT = $09 ;Horizontal Tab +ASC_LF = $0A ;Line Feed +ASC_VT = $0B ;Vertical Tab +ASC_FF = $0C ;Form Feed +ASC_CR = $0D ;Carriage Return +ASC_NAK = $15 ;Negative Acknowledge +ASC_CAN = $18 ;Cancel +ASC_ESC = $1B ;Escape +ASC_FS = $1C ;File Separator +ASC_GS = $1D ;Group Separator +ASC_US = $1F ;Unit Separator +ASC_SP = $20 ;Space +LARROW = ASC_BS ;Left Arrow +RARROW = ASC_NAK ;Right Arrow +UARROW = ASC_VT ;Up Arrow +DARROW = ASC_LF ;Down Arrow +; +; Miscellaneous Equates +; +TRUE = $80 +FALSE = $00 +BITON0 = $01 +BITON2 = $04 +BITON3 = $08 +BITON4 = $10 +BITON5 = $20 +BITON6 = $40 +BITON7 = $80 +BITOFF0 = $FE +BITOFF4 = $EF +BITOFF5 = $DF +BITOFF7 = $7F +BUFMAX = $80 ;Maximum buffer size +TEXTCSA = $C00 ;Text character set address +; .PAGE +;----------------------------------------------------------------------- +; +; SOS Device Handler Interface +; +;----------------------------------------------------------------------- +; +SOSINT = $C0 +REQCODE = SOSINT+0 ;SOS request code +BUFFPTR = SOSINT+2 ;Buffer pointer +REQCNT = SOSINT+4 ;Requested count +RTNCNT = SOSINT+8 ;Returned count +SCCODE = SOSINT+2 ;Status / Control code +SCLIST = SOSINT+3 ;Status / Control list +; +; +;----------------------------------------------------------------------- +; +; Zero Page Data (preserved) and Zero Page Save Area +; +;----------------------------------------------------------------------- +; +ZPDATA = SOSINT+10 +BASEPTRS = ZPDATA+0 ;Screen memory base pointers +BASE1 = BASEPTRS+0 ; even col. / text bytes +BASE2 = BASEPTRS+2 ; odd col. / color bytes +ZPLENGTH = 4 +; +ZPSAVE .RES ZPLENGTH +; +; +;----------------------------------------------------------------------- +; +; Zero Page Data (temporary) +; +;----------------------------------------------------------------------- +; +WORKPTRS = ZPDATA+ZPLENGTH +WORK1 = WORKPTRS+0 +WORK2 = WORKPTRS+2 +COUNT = WORKPTRS+4 ;Current I/O count +ONEBYTE = COUNT+2 ;One byte console read flag +BLANK = ONEBYTE+1 +TEMPX = BLANK+1 +FLAGS = TEMPX+1 +TEMP1 = FLAGS+1 +TEMP2 = TEMP1+1 +TEMP3 = TEMP2+1 +TEMP4 = TEMP3+1 + +; .PAGE +;----------------------------------------------------------------------- +; +; Console State Table +; +;----------------------------------------------------------------------- +; +CONSTTBL = * ;Console state table +; +ANYKYEVNT .RES 5 ;Any Key Event parameters +ATTNEVNT .RES 5 ;Attention Event parameters +ATTNCHAR .BYTE 0 ;Attention character +; +DFLTTBL = * ;This RES initialized from default values +; +KYBDMODE .BYTE 0 ;Console/Keyboard mode flag +NEWLINE .BYTE 0 ;New Line flag +NEWLNCHR .BYTE 0 ;New Line character +NOWAIT .BYTE 0 ;No Wait flag +ECHO .BYTE 0 ;Screen Echo flag +CHCPYFLG .BYTE 0 ;Character Copy flag +CHCPYCHR = ASC_NAK ;Character Copy character +CHDELFLG .BYTE 0 ;Character Delete flag +CHDELCHR = ASC_BS ;Character Delete character +LNDELFLG .BYTE 0 ;Line Delete flag +LNDELCHR = ASC_CAN ;Line Delete character +ESCAPE .BYTE 0 ;Escape Mode flag +; +SCRSTTBL = * ;Screen state table +; +HMODE .BYTE 0 ;Hardware mode +SMODE .BYTE 0 ;Software mode +TPX .BYTE 0 ;Text position +TPY .BYTE 0 +VPL .BYTE 0 ;Viewport +VPR .BYTE 79 +VPT .BYTE 0 +VPB .BYTE 23 +TCF .BYTE $0F ;Text color +TCB .BYTE 00 +; +SCRSTLEN = *-SCRSTTBL +; +DFLTLEN = *-DFLTTBL +; +SCRSTSAV .RES SCRSTLEN ;Saved screen state table +; +CONSTLEN = *-CONSTTBL +; .PAGE +;---------------------------------------------------------------------- +; +; Default Values for State Table +; +;---------------------------------------------------------------------- +; +DFLTVAL .BYTE FALSE ;Console / Keyboard flag + .BYTE FALSE ;Newline flag + .BYTE ASC_CR ;Newline character + .BYTE FALSE ;Nowait flag + .BYTE TRUE ;Screen echo flag + .BYTE TRUE ;Character copy flag + .BYTE TRUE ;Character delete flags + .BYTE TRUE ;Line delete flags + .BYTE TRUE ;Escape mode flags + .BYTE 02 ;Hardware mode + .BYTE $0D ;Software mode + .BYTE 0 ;Cursor position + .BYTE 0 + .BYTE 0 ;Viewport + .BYTE 79 + .BYTE 0 + .BYTE 23 + .BYTE $0F ;Text colors + .BYTE 00 +; .PAGE +;----------------------------------------------------------------------- +; +; Private Variable Storage +; +;----------------------------------------------------------------------- +; +KYBDBUFS = $1500 ;Type ahead buffers +KABUF = KYBDBUFS +KBBUF = KYBDBUFS+BUFMAX +XFORMTBL = $1700 ;Keyboard transform table +; +KADATA .BYTE 0 ;Temp Storage +KBDATA .BYTE 0 ; for Interrupt Processing +; +KEYCNT .BYTE 0 ;Buffered keystroke count +BUFSIZ .BYTE 0 ;Current buffer size +BUFHEAD .BYTE 0 ;Index of first character +BUFTAIL .BYTE 0 ;Index of last character +; +OPENFLG .BYTE 0 ;Device open flag +READING .BYTE 0 ;Read in progress flag +DSPLYCTL .BYTE 0 ;Display control characters +; +SMFLAGS = * +SMINV .BYTE 0 ;Inverse video +SMCURSOR .BYTE 0 ;Cursor enabled +SMSCROLL .BYTE 0 ;Scroll flag +SMAUTOCR .BYTE 0 ;Auto CR +SMAUTOLF .BYTE 0 ;Auto LF +SMAUTOADV .BYTE 0 ;Auto advance +; +VPHMAX .BYTE 79 ;viewport maximum horizontal index +VPVMAX .BYTE 23 ;viewport maximum vertical index +TCOLOR .BYTE $F0 ;text fg/bg color byte +; +CTLINDX .BYTE 0 ;function buffer index +CTLBUFF .RES 8 ;control function buffer +CTLQUOTA .BYTE 0 ;parameter quota +; +DNLDFLG .BYTE 00 ;Bit 7=Active, Bit 6=Request +DNLDCEL .BYTE 00 ;Current download cell number +DNLDCHR .BYTE 00 ;Current download ASCII code +DNLDIMG .WORD 0000 ;Pointer to character image +; .PAGE +;---------------------------------------------------------------------- +; +; Addresses used as subroutine parameters and SIR request tables +; +;---------------------------------------------------------------------- +; +ANYKYPARM .WORD ANYKYEVNT +ATTNPARM .WORD ATTNEVNT +; +KYBDSADR .WORD KYBDSTBL +KYBDSTBL .BYTE 2,0 ;Keyboard interrupt + .WORD KYBDMIH +KYBDBANK .BYTE 0 +KYBDSSIZ = *-KYBDSTBL +; +DNLDSADR .WORD DNLDSTBL +DNLDSTBL .BYTE 5,0,0,0,0 ;VBL positive + .BYTE 6,0 ;VBL negative + .WORD DNLDINT +DNLDBANK .BYTE 0 + .BYTE $10,0,0,0,0 ;Character download / Graphics scroll +DNLDSSIZ = *-DNLDSTBL +; +SYNCSADR .WORD SYNCSTBL +SYNCSTBL .BYTE 5,0,0,0,0 ;VBL positive +SYNCSSIZ = *-SYNCSTBL +; +; +;--------------------------------------- +; +; Base Calculator Address Tables +; +;--------------------------------------- +; +BASL .BYTE $00,$80,$00,$80 + .BYTE $00,$80,$00,$80 + .BYTE $28,$A8,$28,$A8 + .BYTE $28,$A8,$28,$A8 + .BYTE $50,$D0,$50,$D0 + .BYTE $50,$D0,$50,$D0 +BASH .BYTE $04,$04,$05,$05 + .BYTE $06,$06,$07,$07 + .BYTE $04,$04,$05,$05 + .BYTE $06,$06,$07,$07 + .BYTE $04,$04,$05,$05 + .BYTE $06,$06,$07,$07 +; .PAGE +;---------------------------------------------------------------------- +; +; Escape Command and Escape Operator Tables +; +;---------------------------------------------------------------------- +; +ESCCMD .BYTE "B" ;Viewport bottom right + .BYTE "T" ;Viewport top left + .BYTE "V" ;Clear Viewport + .BYTE "S" ;Clear Screen + .BYTE "P" ;Clear to End of Page + .BYTE "L" ;Clear to End of Line + .BYTE "H" ;Home Cursor + .BYTE ASC_BS ;Move left + .BYTE ASC_NAK ;Move right + .BYTE ASC_VT ;Move up + .BYTE ASC_LF ;Move down +ECMDCNT = *-ESCCMD +; +ESCOP .BYTE ASC_ETX + .BYTE ASC_STX + .BYTE ASC_SOH + .BYTE ASC_FS + .BYTE ASC_GS + .BYTE ASC_US + .BYTE ASC_FF + .BYTE ASC_BS + .BYTE ASC_HT + .BYTE ASC_VT + .BYTE ASC_LF + +; .PAGE +;----------------------------------------------------------------------- +; +; Console Device Handler +; +; This is the device handler's entry point. It sets the extended +; addressing bytes to zero and moves in the permanant zero page +; data, then switches to the appropriate request handler. If the +; request handler modifies the permanant zero page data, it must +; call ZPOUT before it exits to SOS. +; +;----------------------------------------------------------------------- +; +CNSLDH = * + LDX #$FF-ZPDATA + LDY #00 + TYA +@010 STA $1400+ZPDATA,X ;Set extend bytes to zero + CPX #ZPLENGTH + BCS @020 + LDA ZPSAVE,X + STA ZPDATA,X ;Set up zero page data + TYA +@020 DEX + BPL @010 +; + SWITCH REQCODE,8,CREQSW +; +; +CBADREQ LDA #XREQCODE ;Invalid request code + JSR SYSERR +; +CNOTOPEN LDA #XNOTOPEN ;Console is not open + JSR SYSERR +; +CREQSW .WORD CNSLREAD-1 + .WORD CNSLWRIT-1 + .WORD CNSLSTAT-1 + .WORD CNSLCNTL-1 + .WORD CBADREQ-1 + .WORD CBADREQ-1 + .WORD CNSLOPEN-1 + .WORD CNSLCLOS-1 + .WORD CNSLINIT-1 +; .PAGE +;----------------------------------------------------------------------- +; +; Keyboard Interrupt Handler +; +;----------------------------------------------------------------------- +; +KYBDMIH = * +; +; Read keyboard data and clear interrupt +; + LDX #KYBDCLR + LDA KAPORT ;Read data port + BMI @010 + STX E_IFR ;No data ready -- clear + RTS ; interrupt and exit +@010 AND #BITOFF7 + STA KADATA + LDA KBPORT ;Read status port + EOR #$3C + STA KBDATA + STX E_IFR ;Clear interrupt + STX KYBDSTRB ; and keyboard strobe + BMI KIHSPCL + LDA KADATA + CMP #ASC_CR + BNE KIHXFORM + LDA KBDATA + AND #BITON2 ;Transform CR iff + BNE KIHXFORM ; CTRL is held down + JMP KIHA1KY +; +; Special key +; Check for console control commands +; Do not transform character code +; +KIHSPCL AND #$36 ;Isolate A1, A2, CTRL, & SHIFT + CMP #BITON2 + BEQ @050 +@010 JMP KIHA1KY ;Not a console control command +@050 LDA KADATA + CMP #'5' ;Toggle video? + BCC @010 + BNE @060 + LDA SCRNMODE + EOR #BITON7 + STA SCRNMODE + RTS +@060 CMP #'6' ;Flush input buffer? + BNE @070 + LDA #00 + STA KEYCNT + STA BUFHEAD + STA BUFTAIL + RTS +@070 CMP #'7' ;Suspend screen output? + BNE @080 + LDA SUSPFLSH + EOR #BITON7 + STA SUSPFLSH + RTS +@080 CMP #'8' ;Display control characters? + BNE @090 + LDA DSPLYCTL + EOR #BITON7 + STA DSPLYCTL + RTS +@090 CMP #'9' ;Flush screen output? + BNE KIHA1KY + LDA SUSPFLSH + AND #BITOFF7 + EOR #BITON6 + STA SUSPFLSH + RTS +; +; Standard key +; Transform character code +; Check for alpha lock +; +KIHXFORM LDA KADATA +@010 CMP #$7B ;Convert ASCII code to + BCC @030 ; transform table index + CMP #$7E + BCC @020 + EOR #$C0 + BNE @040 +@020 AND #$5F +@030 ORA #$C0 +@040 TAX + LDA KBDATA ;Get control & shift keys + LSR A + AND #03 + ORA XFORMTBL,X ;OR in key number + TAX + LDA XFORMTBL,X ;Need to test alpha lock? + BPL @050 + LDA KBDATA ;Check alpha lock key + AND #BITON3 + BEQ @050 + TXA + ORA #BITON0 ;Force shift key on + TAX +@050 LDA XFORMTBL,X ;Get key code + AND #BITOFF7 + STA KADATA +; +; Set bit 7 according to Apple 1 key +; +KIHA1KY LDA KBDATA + AND #BITON4 + BEQ KIHCKEV + LDA KADATA + ORA #BITON7 + STA KADATA +; +; Check for Any Key and Attention events +; +KIHCKEV BIT READING ;If reading, + BMI @010 ; ignore Any Key event + LDA ANYKYEVNT ;Check Any Key Event + BEQ @010 + LDX ANYKYPARM + LDY ANYKYPARM+1 + JSR QUEEVENT ;Queue the event + LDA #FALSE + STA ANYKYEVNT ;Disable Any Key event + BEQ @020 +@010 LDA ATTNEVNT ;Check Attention Event + BEQ KIHBFCH + LDA KADATA + CMP ATTNCHAR + BNE KIHBFCH + LDX ATTNPARM + LDY ATTNPARM+1 + JSR QUEEVENT ;Queue the event + LDA #FALSE + STA ATTNEVNT ;Disable Attention event +@020 STA READING ;Terminate any read in progress + STA KEYCNT ;Flush the input buffer + STA BUFHEAD + STA BUFTAIL + STA SUSPFLSH ;Clear suspend & flush flags +; +; Buffer the character +; +KIHBFCH LDX BUFSIZ ;Buffering enabled? + BEQ @030 + DEX + CPX KEYCNT ;Any room in buffer? + BCS @010 + BIT BELL ;Buffer overflow + BCC @030 +@010 INC KEYCNT ;Bump the key count + LDX BUFTAIL + LDA KADATA + STA KABUF,X ;Buffer the keystroke + LDA KBDATA + STA KBBUF,X + INX + CPX BUFSIZ ;Bump buffer tail pointer + BCC @020 + LDX #0 +@020 STX BUFTAIL +@030 RTS +; .PAGE +;----------------------------------------------------------------------- +; +; Subroutine GETKEY +; +; This subroutine gets the next keystroke from the type ahead buffer. +; On entry, the interrupt system must be enabled but the keyboard +; interrupt must be masked. On exit, if carry is clear, A contains +; the keyboard A port data and X contains the keyboard B port data; +; Y is undefined. If carry is set, no data is returned; either the +; buffer was empty and the NOWAIT flag is true, or the read was +; terminated by the interrupt handler. +; +;----------------------------------------------------------------------- +; +GETKEY = * + LDA KEYCNT ;Anything in the buffer? + BNE @030 ; Yes + PHP + SEI + LDA SCRNMODE + ORA #BITON7 + STA SCRNMODE ;Turn on video + LDA E_REG + ORA #BITON5 + STA E_REG + PLP + BIT NOWAIT ;Check the NOWAIT flag + BPL @010 + ASL READING ;Clear the READING flag, + RTS ; set carry, and exit +; +@010 LDX BUFSIZ ;Preserve buffer size in X + LDA #1 ;Set buffer size to 1 + STA BUFSIZ + LDA #KYBDENBL ;Unmask the keyboard + STA E_IER + BIT ESCAPE ;In ESCAPE mode? + BVC @020 ; No + CLC + LDA TPX ;Preserve current cursor and + LDY HMODE ; replace it with plus sign + BPL @015 + LSR A + BCC @015 + TAY + LDA (BASE2),Y + PHA + AND #BITON7 + ORA #$2B + STA (BASE2),Y + BCS @020 +@015 TAY + LDA (BASE1),Y + PHA + AND #BITON7 + ORA #$2B + STA (BASE1),Y +@020 LDA KEYCNT ;Wait for a keystroke + BEQ @020 + BVC @026 ;Not in ESCAPE mode + PLA ;Restore original cursor + BCC @024 + STA (BASE2),Y + BCS @026 +@024 STA (BASE1),Y +@026 LDA #KYBDDSBL ;Mask the keyboard + STA E_IER + STX BUFSIZ ;Restore the buffer size + SEC + BIT READING ;Check the reading flag + BPL @060 ; Exit with carry set +; +@030 LDY BUFHEAD ;Get buffer index of keystroke + DEC KEYCNT + BNE @040 ;If KEYCNT = 0 + LDA #0 + STA BUFHEAD ; then BUFHEAD := BUFTAIL := 0 + STA BUFTAIL + BEQ @050 +@040 INC BUFHEAD ; else BUFHEAD := BUFHEAD + 1 + LDA BUFHEAD + CMP BUFSIZ ;If BUFHEAD >= BUFSIZ + BCC @050 + LDA #0 ; then BUFHEAD := 0 + STA BUFHEAD +@050 LDA KABUF,Y ;Load the A and B port data + LDX KBBUF,Y + CLC +@060 RTS +; .PAGE +;----------------------------------------------------------------------- +; +; Subroutine SCRNECHO +; +; This subroutine writes a single character to the screen. On entry, +; the character must be in A. On exit, all registers are undefined. +; +;----------------------------------------------------------------------- +SCRNECHO = * + BIT ECHO ;Screen Echo enabled? + BPL @010 + PHA + JSR CURSOR ;Remove cursor + PLA + JSR PRINT ;Print the character + JSR CURSOR ;Restore cursor +@010 RTS +; +; +;----------------------------------------------------------------------- +; +; Subroutine BACKSP +; +; This subroutine performs the screen backspace when the console +; deletes an input character. On entry, the input buffer pointer +; must point to the character to be deleted and the overflow flag +; must be set to indicate that the character should be erased, or +; clear to indicate that it should be left on the screen. On exit, +; all registers are undefined. +; +;----------------------------------------------------------------------- +BACKSP = * + LDA ECHO + BPL @020 ;Screen Echo not enabled + LDY #0 + LDA (BUFFPTR),Y ;Printable character? + CMP #ASC_SP + BCC @020 + PHP ;Save overflow flag + JSR CURSOR ;Remove cursor + LDA #ASC_BS + JSR PRINT ;Backspace + PLP + BVC @010 ;Don't erase + LDA #ASC_SP + JSR PRINT ;Erase the character + LDA #ASC_BS + JSR PRINT +@010 JSR CURSOR ;Restore cursor +@020 RTS + +; .PAGE +;----------------------------------------------------------------------- +; +; Console Read Request +; +; Parameters: +; BUFFPTR: Pointer to caller's data buffer +; REQCNT: Requested read count +; RTNCNT: Pointer to actual read count +; +; Zero Page Temporary Storage +; COUNT: Number of bytes read +; ONEBYTE: TRUE if REQCNT = 1 +; +; If the ECHO or ESCAPE functions are enabled, this segment will call +; PRINT to display a character or perform a screen control function. +; +;----------------------------------------------------------------------- +; +CNSLREAD = * +; +; Initialize read variables +; + BIT OPENFLG + BMI @010 + JMP CNOTOPEN +@010 BIT KYBDMODE ;Keyboard mode? + BMI @030 + LDA SMCURSOR ;Save cursor status + PHA + BMI @020 + LDA #ASC_ENQ ;Turn on cursor + JSR SCRNECHO +@020 LDA #FALSE + STA ONEBYTE ;Clear one byte read flag + LDA REQCNT+1 + BNE @040 + LDA REQCNT + CMP #1 + BNE @040 + ROR ONEBYTE ;Set one byte read flag + BMI @040 +; +@030 LDA REQCNT ;Make requested count even + AND #BITOFF0 + STA REQCNT +; +@040 LDA ESCAPE + AND #BITON7 + STA ESCAPE ;Clear escape pending + LDA #0 + STA COUNT + STA COUNT+1 ;Zero bytes read count + PHP + SEI + STA SUSPFLSH ;Clear suspend & flush flags + LDA #KYBDDSBL + STA E_IER ;Mask the keyboard + LDA #TRUE + STA READING ;Set the READING flag + PLP +; +; Main read loop +; +CNSLLOOP LDA COUNT ;If COUNT >= REQCNT + CMP REQCNT ; then goto CNSLEXIT + LDA COUNT+1 + SBC REQCNT+1 + BCC @020 +@010 JMP CNSLEXIT +; +@020 JSR GETKEY ;Get next keystroke + BCS @010 + BIT KYBDMODE ;Console or Keyboard mode? + BPL TSTESCAPE +; +; Keyboard mode read +; +KYBDRDY PHA ;Save ASCII byte + LDY #0 + STA (BUFFPTR),Y ;Store data byte in buffer + INY + TXA + STA (BUFFPTR),Y ;Store status byte in buffer + LDA #02 + JMP BUMPCNT ;Go update COUNT and BUFFPTR +; +; Console mode read +; +TSTESCAPE BIT ECHO ;Test for Escape Mode + BPL TSTCHDEL + BIT ESCAPE + BPL TSTCHDEL + BVC @040 ;Escape not pending + LDY #ECMDCNT-1 + CMP #'a' + BCC @010 + CMP #'{' + BCS @010 + AND #BITOFF5 ;Upshift lower case alpha +@010 CMP ESCCMD,Y ;Search for escape command + BEQ @020 + DEY + BPL @010 + ASL ESCAPE ;Not found -- clear pending flag + BCS @030 +@020 LDA ESCOP,Y ;Get screen control character + JSR SCRNECHO +@030 JMP CNSLLOOP +; +@040 CMP #ASC_ESC ;Is this an ESC? + BNE TSTCHDEL + ROR ESCAPE ;Set escape pending + BMI @030 +; +TSTCHDEL BIT ONEBYTE ;Test for character delete + BMI TSTLNDEL + BIT CHDELFLG + BPL TSTLNDEL + CMP #CHDELCHR + BNE TSTLNDEL + LDA COUNT ;Anything to delete? + ORA COUNT+1 + BEQ @030 + LDA COUNT + BNE @010 + DEC COUNT+1 ;Decrement current read count +@010 DEC COUNT + LDA BUFFPTR + BNE @020 + DEC BUFFPTR+1 ;Decrement buffer pointer +@020 DEC BUFFPTR + JSR BACKSP ;Backspace +@030 JMP CNSLLOOP +; +TSTLNDEL BIT ONEBYTE ;Test for line delete + BMI TSTCHCPY + BIT LNDELFLG + BPL TSTCHCPY + CMP #LNDELCHR + BNE TSTCHCPY + LDA ECHO + BPL @050 + BVC @040 +; +@010 LDA COUNT ;Anything to delete? + ORA COUNT+1 + BEQ @060 + LDA COUNT + BNE @020 + DEC COUNT+1 ;Decrement current read count +@020 DEC COUNT + LDA BUFFPTR + BNE @030 + DEC BUFFPTR+1 ;Decrement buffer pointer +@030 DEC BUFFPTR + BIT LNDELFLG + JSR BACKSP ;Backspace + JMP @010 +; +@040 LDA #'\' + JSR SCRNECHO ;Write "\ CR LF" + LDA #ASC_CR + JSR SCRNECHO + LDA #ASC_LF + JSR SCRNECHO +@050 SEC + LDA BUFFPTR ;Reset buffer pointer + SBC COUNT + STA BUFFPTR + LDA BUFFPTR+1 + SBC COUNT+1 + STA BUFFPTR+1 + LDA #0 ;Reset current read count + STA COUNT + STA COUNT+1 +@060 JMP CNSLLOOP +; +TSTCHCPY BIT ECHO ;Test for character copy + BPL CNSLRDY + BIT CHCPYFLG + BPL CNSLRDY + CMP #CHCPYCHR + BNE CNSLRDY + JSR SCRNPICK ;Copy character from screen + ASL A + CMP #$40 + ROR A + EOR #BITON7 +; +CNSLRDY PHA ;Save character for new line test + LDY #0 + STA (BUFFPTR),Y ;Store character in buffer +; + BIT ECHO ;Echo enabled? + BPL @020 + BVS @010 + CMP #$20 ;Check for control character + BCC @020 +@010 JSR SCRNECHO +@020 LDA #01 +; +BUMPCNT PHA + CLC + ADC COUNT ;Update current read count + STA COUNT + BCC @010 + INC COUNT+1 +@010 PLA + CLC + ADC BUFFPTR ;Update buffer pointer + STA BUFFPTR + BCC TSTNEWLN + INC BUFFPTR+1 + LDA BUFFPTR+1 + CMP #$FF + BCC TSTNEWLN + SBC #$80 ;Wrap buffer at FF page + STA BUFFPTR+1 + INC $1400+BUFFPTR+1 +; +TSTNEWLN PLA ;Test for New Line + BIT NEWLINE + BPL @010 + CMP NEWLNCHR + BEQ CNSLEXIT +@010 JMP CNSLLOOP +; +CNSLEXIT ASL READING ;Clear the READING flag + LDA #KYBDENBL + STA E_IER ;Unmask the keyboard + LDY #0 + LDA COUNT ;Return the actual byte count + STA (RTNCNT),Y + INY + LDA COUNT+1 + STA (RTNCNT),Y + BIT KYBDMODE + BMI @020 + PLA + BMI @010 + LDA #ASC_ACK ;Turn off cursor + JSR SCRNECHO +@010 JSR ZPOUT +@020 RTS + +; .PAGE +;----------------------------------------------------------------------- +; +; Console Write Request +; +; Parameters: +; BUFFPTR: Pointer to caller's data buffer +; REQCNT: Number of bytes to write +; +; Zero Page Temporary Storage +; COUNT: Number of bytes written +; +; Additional zero page data may be used to perform screen +; control functions. +; +;----------------------------------------------------------------------- +; +CNSLWRIT = * + BIT OPENFLG + BMI @010 + JMP CNOTOPEN +@010 JSR CURSOR ;Remove Cursor + LDA #0 + STA COUNT ;Zero COUNT + STA COUNT+1 +; +@020 LDA COUNT ;Check for end of buffer + CMP REQCNT + LDA COUNT+1 + SBC REQCNT+1 + BCS @060 ;Go Exit +@030 BIT SUSPFLSH ;Check suspend and flush flags + BMI @030 ; Suspend + BVS @050 ; Flush + LDY #0 + LDA (BUFFPTR),Y ;Get next byte + JSR PRINT ;Print the byte + INC BUFFPTR + BNE @040 ;Bump pointer + INC BUFFPTR+1 + BNE @040 + LDA #$80 + STA BUFFPTR+1 ;Process buffer wrap around + INC $1400+BUFFPTR+1 +@040 INC COUNT + BNE @020 ;Bump bytes read count + INC COUNT+1 + JMP @020 +; +@050 LDA #00 + STA CTLINDX ;Clear any pending cntl function +; +@060 JSR CURSOR ;Restore cursor + JMP ZPOUT ;Save Zero Page data and exit +; .PAGE +;----------------------------------------------------------------------- +; +; Subroutine PRINT +; +; This routine processes a single byte of output. Characters are +; printed by calling DISPLAY. Screen control functions are processed +; by accumulating any required parameters in CTLBUFF then switching +; to the appropriate screen control routine. +; +; Parameters: +; A: The byte to process +; +; Exit: +; A, X, Y: Undefined +; +;----------------------------------------------------------------------- +; +PRINT = * + LDY CTLINDX ;Get control function index + BNE @010 + ORA DSPLYCTL + CMP #ASC_SP ;Display or control? + BCS DISPLAY + TAX + LDA QUOTATBL,X ;Get function quota + BEQ @020 + STA CTLQUOTA + TXA +@010 STA CTLBUFF,Y ;Save function character + INY + STY CTLINDX ;Update buffer index + CPY CTLQUOTA ;See if quota filled + BCC @020 + LDY #0 + STY CTLINDX ;Zero buffer index + SWITCH CTLBUFF,,CTLSWTBL,'*' +@020 RTS +; .PAGE +;---------------------------------------------------------------------- +; +; Subroutine DISPLAY +; +; This routine displays a single character. If auto advance is +; enabled, it calls CF_HT to advance the cursor. +; +; Parameters: +; A: The character to be displayed +; +; Exit: +; A, X, Y: Undefined +; +;---------------------------------------------------------------------- +; +DISPLAY = * + ORA #$80 ;set hi-bit + EOR SMINV ;set normal or inverse + PHA ;(for safe keeping) + BIT HMODE ;80 column text? + BPL @010 + LDA TPX + LSR A ;80 col: X=TPX/2 + TAY ;carry bit clear? + BCC @020 ;yes: use page 1 + PLA + STA (BASE2),Y ;80 col page two + BCS @030 +@010 LDY TPX ;40 col: X=TPX + LDA TCOLOR + STA (BASE2),Y ;set color byte +@020 PLA + STA (BASE1),Y ;80 col page one +@030 BIT SMAUTOADV ;if auto advance, + BPL @040 + JMP CF_HT ;advance cursor +@040 RTS +; .PAGE +;---------------------------------------------------------------------- +; +; Control Function Quota and Switch Tables +; +;---------------------------------------------------------------------- +QUOTATBL = * ;The Control Function Quota Table + .RES 1,0 ; contains the total number of + .RES 15,1 ; bytes required by the function, + .RES 1,2 ; including the function character + .RES 2,1 ; itself. A zero indicates that + .RES 2,2 ; the function is unimplemented. + .RES 1,2 + .RES 1,1 + .RES 3,2 + .RES 1,3 + .RES 1,0 + .RES 4,1 +CTLSWTBL = * + .WORD CF_NUL-1 ;00 no-op + .WORD CF_SOH-1 ;01 Save Environment & Release Viewport + .WORD CF_STX-1 ;02 Set Viewport Upper Left + .WORD CF_ETX-1 ;03 Set Viewport Lower Right + .WORD CF_EOT-1 ;04 Restore Environment + .WORD CF_ENQ-1 ;05 Cursor On + .WORD CF_ACK-1 ;06 Cursor Off + .WORD CF_BEL-1 ;07 Audible signal + .WORD CF_BS-1 ;08 Backspace + .WORD CF_HT-1 ;09 Forward Space + .WORD CF_LF-1 ;0A Line Feed + .WORD CF_VT-1 ;0B Reverse Line Feed + .WORD CF_FF-1 ;0C Home Cursor + .WORD CF_CR-1 ;0D Carriage Return + .WORD CF_SO-1 ;0E Screen Off + .WORD CF_SI-1 ;0F Screen On + .WORD CF_DLE-1 ;10 Set Text Mode + .WORD CF_DC1-1 ;11 Normal Video + .WORD CF_DC2-1 ;12 Inverse Video + .WORD CF_DC3-1 ;13 Foreground Color + .WORD CF_DC4-1 ;14 Background Color + .WORD CF_NAK-1 ;15 Set Text Options + .WORD CF_SYN-1 ;16 Sync on VBL + .WORD CF_ETB-1 ;17 Horizontal Shift + .WORD CF_CAN-1 ;18 Go to X + .WORD CF_EM-1 ;19 Go to Y + .WORD CF_SUB-1 ;1A Go to X,Y + .WORD CF_ESC-1 ;1B No-op + .WORD CF_FS-1 ;1C Clear Screen + .WORD CF_GS-1 ;1D Clear to End of Screen + .WORD CF_RS-1 ;1E Clear Line + .WORD CF_US-1 ;1F Clear to End of Line + +; .PAGE +;---------------------------------------------------------------------- +; +; Screen Control Functions +; +; These routines perform all screen control functions. +; +; Parameters: +; All parameters are accumulated in CTLBUFF +; +; Exit: +; A, X, Y: Undefined +; +;---------------------------------------------------------------------- +; +CF_NUL = * +CF_ESC = * + RTS ;NO-OP +; +CF_SOH = * ;Save & Release Viewport + LDY #SCRSTLEN +@010 LDA SCRSTTBL-1,Y + STA SCRSTSAV-1,Y + DEY + BNE @010 + CLC + LDA TPX + ADC VPL + STA TPX ;retain X posn + LDA TPY + ADC VPT + STA TPY ;retain y posn + LDA #0 + STA VPL ;zero left margin + STA VPT ;zero top margin + LDA #$FF + STA VPR ;Let VERIFY set the right edge + STA VPB ; and bottom margin + JMP VERIFY +; +CF_STX = * ;SET VIEWPORT UPPER LEFT + CLC + LDA VPL + ADC TPX ;at cursor posn + STA VPL ;set left margin + LDA VPT + ADC TPY + STA VPT ;set top margin + LDA #0 + STA TPX ;reset cursor X + STA TPY ; and cursor Y + JMP VERIFY ;and verify +; +CF_ETX = * ;SET VIEWPORT LOWER RIGHT + CLC + LDA TPX + ADC VPL + STA VPR ;set left margin + LDA TPY + ADC VPT ;& bottom margin + STA VPB + JMP VERIFY ;and verify +; +CF_EOT = * ;RESTORE VIEWPORT + LDY #SCRSTLEN +@010 LDA SCRSTSAV-1,Y + STA SCRSTTBL-1,Y + DEY + BNE @010 + JMP VERIFY +; +CF_ENQ = * ;ENABLE CURSOR + LDA SMODE + ORA #BITON4 + STA SMODE + LDA #TRUE + STA SMCURSOR + RTS +; +CF_ACK = * ;DISABLE CURSOR + LDA SMODE + AND #BITOFF4 + STA SMODE + LDA #FALSE + STA SMCURSOR + RTS +; +CF_BEL = * ;Sound Bell + BIT BELL + RTS +; +CF_BS = * ;BACKSPACE + DEC TPX + BPL @020 + BIT SMAUTOCR ;BS at left: + BPL @010 + LDA VPHMAX ;Wrap to right + STA TPX ; edge of viewport + JMP CF_VT +@010 INC TPX +@020 RTS +; +CF_HT = * ;ADVANCE + LDA TPX + CMP VPHMAX + BCS @010 ;at edge? + INC TPX ;no: advance + RTS +@010 BIT SMAUTOCR ;auto CR on? + BPL CF_EXIT + LDA #0 ;yes: wrap to + STA TPX ;left margin + JMP CF_LF ;& line feed +; +CF_LF = * ;LINE FEED + LDA TPY + CMP VPVMAX + BCS @010 ;at edge? + INC TPY ;no: move down + JMP TBASCAL ;calc base address +@010 BIT SMSCROLL ;auto scroll? + BPL CF_EXIT + LDA #00 + JMP SCROLL ;yes: go to it +; +CF_VT = * ;REVERSE LINE FEED + LDA TPY + BEQ @010 ;at top? + DEC TPY ;no: do it + JMP TBASCAL ;calc base address +@010 BIT SMSCROLL ;auto scroll? + BPL CF_EXIT + LDA #$80 + JMP SCROLL +; +CF_FF = * ;FORM FEED + LDA #0 + STA TPX ;reset TPX + STA TPY ; and TPY + JMP TBASCAL ;calc base address +; +CF_CR = * ;CARRIAGE RETURN + LDA #0 + STA TPX ;reset TPX + BIT SMAUTOLF ;auto LF set? + BPL CF_EXIT + JMP CF_LF ;yes: go to it +; +CF_SO = * ;SCREEN OFF + LDA #FALSE + STA SCRNMODE + JMP VERIFY +; +CF_SI = * ;SCREEN ON + LDA #TRUE + STA SCRNMODE + JMP VERIFY +; +CF_DLE = * ;SET HARDWARE MODE + LDA CTLBUFF+1 + STA HMODE + JMP VERIFY +; +CF_DC1 = * ;NORMAL VIDEO + LDA SMODE + AND #BITOFF5 ;reset INVERSE bit + STA SMODE + LDA #FALSE + STA SMINV +CF_EXIT RTS +; +CF_DC2 = * ;INVERSE VIDEO + LDA SMODE + ORA #BITON5 ;set INVERSE bit + STA SMODE + LDA #TRUE + STA SMINV + RTS +; +CF_DC3 = * ;FOREGROUND COLOR + LDA CTLBUFF+1 + STA TCF + JMP VERIFY ;set TCOLOR +; +CF_DC4 = * ;BACKGROUND COLOR + LDA CTLBUFF+1 + STA TCB + JMP VERIFY ;set TCOLOR +; +CF_NAK = * ;SET SOFTWARE MODE + LDA CTLBUFF+1 + AND #$0F + STA CTLBUFF+1 + LDA SMODE ;Save bits 7-4 + AND #$F0 + ORA CTLBUFF+1 + STA SMODE + JMP VERIFY +; +CF_SYN = * ;SYNCHRONIZE WITH VBL + LDA #SYNCSSIZ + LDX SYNCSADR + LDY SYNCSADR+1 + JSR ALLOCSIR ;Allocate CB2 for VBL + BCS CF_EXIT + JSR CURSOR ;Restore cursor while waiting + PHP + SEI + LDA E_PCR + AND #$1F + ORA #$60 ;Set up CB2 to monitor + STA E_PCR ; VBL positive edge + LDA #08 + STA E_IER + STA E_IFR + PLP +@010 BIT E_IFR ;Wait for VBL edge + BEQ @010 + JSR CURSOR ;Remove cursor + LDA #SYNCSSIZ + LDX SYNCSADR + LDY SYNCSADR+1 + JMP DEALCSIR ;Release CB2 resource +; +CF_ETB = * ;HORIZONTAL SCROLL + LDA CTLBUFF+1 +@010 JMP SHIFT +; +CF_CAN = * ;Go To X + LDA CTLBUFF+1 + CMP VPHMAX ;out of range? + BCC @010 + LDA VPHMAX ;Set to right margin +@010 STA TPX + RTS +; +CF_EM = * ;Go To Y + LDA CTLBUFF+1 + CMP VPVMAX ;out of range? + BCC @010 + LDA VPVMAX ;Set to top +@010 STA TPY + JMP TBASCAL ;get base address +; +CF_SUB = * ;Go To X, Y + JSR CF_CAN + LDA CTLBUFF+2 + STA CTLBUFF+1 + JMP CF_EM +; +CF_FS = * ;CLEAR SCREEN + JSR CF_FF + JMP CLREOS +; +CF_GS = * ;CLEAR TO EOS + JMP CLREOS +; +CF_RS = * ;CLEAR LINE + LDA #0 + STA TPX + JMP CLREOL +; +CF_US = * ;CLEAR TO EOL + JMP CLREOL + +; .PAGE +;---------------------------------------------------------------------- +; +; Console Status Request +; +; Parameters: +; SCCODE: Status / Control code +; SCLIST: Pointer to caller's status / control list +; +; Before switching to the appropriate request handling code, +; Y is set to zero. +; +;---------------------------------------------------------------------- +; +CNSLSTAT = * + BIT OPENFLG ;Is the Console open? + BMI @010 + JMP CNOTOPEN +@010 SWITCH SCCODE,18,CSTATSW,'*' + BCS CBADCTL + LDY #0 + RTS +; +CBADCTL LDA #XCTLCODE ;Invalid control code + JSR SYSERR +; +CSTATSW .WORD CSTAT00-1 + .WORD CSTAT01-1 + .WORD CSTAT02-1 + .WORD CSTAT03-1 + .WORD CSTAT04-1 + .WORD CSTAT05-1 + .WORD CSTAT06-1 + .WORD CBADCTL-1 + .WORD CSTAT08-1 + .WORD CSTAT09-1 + .WORD CSTAT10-1 + .WORD CSTAT11-1 + .WORD CSTAT12-1 + .WORD CSTAT13-1 + .WORD CSTAT14-1 + .WORD CSTAT15-1 + .WORD CSTAT16-1 + .WORD CSTAT17-1 + .WORD CSTAT18-1 +; +CSTAT00 RTS ;0 -- NOP +; +CSTAT01 = * ;1 -- Console Status Table + LDA (SCLIST),Y + CMP #CONSTLEN + BCS @010 + LDA #XCTLPARM + JSR SYSERR +@010 LDA #CONSTLEN + STA (SCLIST),Y + TAY +@020 LDA CONSTTBL-1,Y + STA (SCLIST),Y + DEY + BNE @020 + RTS +; +CSTAT02 = * ;2 -- New Line + LDA NEWLINE + STA (SCLIST),Y + INY + LDA NEWLNCHR + STA (SCLIST),Y + RTS +; +CSTAT03 = * ;3 -- Console / Keyboard mode + LDA KYBDMODE + STA (SCLIST),Y + RTS +; +CSTAT04 = * ;4 -- Buffer Size + LDA BUFSIZ + STA (SCLIST),Y + RTS +; +CSTAT05 = * ;5 -- Current Key Count + LDA KEYCNT + STA (SCLIST),Y + RTS +; +CSTAT06 LDY #5 ;6 -- Attention Event +@010 LDA ATTNEVNT,Y + STA (SCLIST),Y + DEY + BPL @010 + RTS +; +CSTAT08 LDY #4 ;8 -- Any Key Event +@010 LDA ANYKYEVNT,Y + STA (SCLIST),Y + DEY + BPL @010 + RTS +; +CSTAT09 = * ;09 -- Read Screen with norm/inv + JSR SCRNPICK + EOR #BITON7 + EOR SMCURSOR + LDY #0 + STA (SCLIST),Y + RTS +; +CSTAT10 = * ;10 -- No Wait Input + LDA NOWAIT + STA (SCLIST),Y + RTS +; +CSTAT11 = * ;11 -- Screen Echo + LDA ECHO + STA (SCLIST),Y + RTS +; +CSTAT12 = * ;12 -- Character Copy + LDA CHCPYFLG + STA (SCLIST),Y + RTS +; +CSTAT13 = * ;13 -- Character Delete + LDA CHDELFLG + STA (SCLIST),Y + RTS +; +CSTAT14 = * ;14 -- Line Delete + LDA LNDELFLG + STA (SCLIST),Y + RTS +; +CSTAT15 = * ;15 -- Escape Functions + LDA ESCAPE + STA (SCLIST),Y + RTS +; +CSTAT16 = * ;16 -- Cursor Position + LDA TPX + STA (SCLIST),Y + INY + LDA TPY + STA (SCLIST),Y + RTS +; +CSTAT17 = * ;17 -- Pick Character + JSR SCRNPICK + ASL A + CMP #$40 + ROR A + EOR #BITON7 + LDY #0 + STA (SCLIST),Y + RTS +; +CSTAT18 = * ;18 -- Screen Dump + LDA HMODE + STA (SCLIST),Y + INY + LDA VPHMAX + STA (SCLIST),Y + INY + LDA VPVMAX + STA (SCLIST),Y + LDA #00 + BIT DSPLYCTL + BMI @010 + JMP SCRNDUMP +@010 STA (SCLIST),Y ;If control characters are being + DEY ; displayed, dump a null viewport + STA (SCLIST),Y + RTS + +; .PAGE +;---------------------------------------------------------------------- +; +; Console Control Request +; +; Parameters: +; SCCODE: Status / Control code +; SCLIST: Pointer to caller's status / control list +; +; Before switching to the appropriate request handler, Y is +; set to zero and A is loaded with the first byte of the list. +; +;---------------------------------------------------------------------- +; +CNSLCNTL = * + BIT OPENFLG ;Console open? + BPL @010 + SWITCH SCCODE,18,CCNTLSW,'*' + BCS @020 + LDY #00 + LDA (SCLIST),Y + RTS +; +@010 JMP CNOTOPEN +; +@020 JMP CBADCTL +; +CCNTLSW .WORD CCNTL00-1 + .WORD CCNTL01-1 + .WORD CCNTL02-1 + .WORD CCNTL03-1 + .WORD CCNTL04-1 + .WORD CCNTL05-1 + .WORD CCNTL06-1 + .WORD CBADCTL-1 + .WORD CCNTL08-1 + .WORD CBADCTL-1 + .WORD CCNTL10-1 + .WORD CCNTL11-1 + .WORD CCNTL12-1 + .WORD CCNTL13-1 + .WORD CCNTL14-1 + .WORD CCNTL15-1 + .WORD LOADSET-1 + .WORD LOAD8-1 + .WORD CCNTL18-1 +; +CCNTL00 LDA E_IER ;0 -- Reset + PHA ;Save current interrupt state + LDA #KYBDDSBL ; and mask off interrupts + STA E_IER + LDA #BUFMAX + STA BUFSIZ ;Set buffer size to maximum + LDA #00 + STA KEYCNT ;Flush buffer + STA BUFHEAD + STA BUFTAIL + STA READING ;No read in progress + STA ANYKYEVNT ;Disable any key event + STA ATTNEVNT ;Disable attention event + STA CTLINDX ;Abort control function in progress + STA DSPLYCTL ;Clear display control char. flag + STA SUSPFLSH ;Clear suspend & flush output flags + JSR CURSOR ;Remove cursor + LDX #DFLTLEN +@010 LDA DFLTVAL-1,X ;Copy configuration RES + STA DFLTTBL-1,X + DEX + BNE @010 + JSR CF_SOH ;Save screen state & verify + JSR CURSOR ;Restore the cursor + JSR ZPOUT ;Save screen zero page + PLA + AND #KYBDENBL ;Restore previous interrupt state + ORA #BITON7 + STA E_IER + RTS +; +CCNTL01 = * ;1 -- Console Status Table + CMP #CONSTLEN + BEQ @010 + LDA #XCTLPARM + JSR SYSERR +@010 JSR CURSOR + LDY #CONSTLEN +@020 LDA (SCLIST),Y + DEY + STA CONSTTBL,Y + BNE @020 + JSR VERIFY + JSR CURSOR + JSR ZPOUT + RTS +; +CCNTL02 = * ;2 -- New Line + AND #BITON7 + STA NEWLINE + INY + LDA (SCLIST),Y + STA NEWLNCHR + RTS +; +CCNTL03 = * ;3 -- Console / Keyboard mode + AND #BITON7 + STA KYBDMODE + RTS +; +CCNTL04 = * ;4 -- Buffer Size + CMP #BUFMAX+1 + BCC @010 + LDA #XCTLPARM + JSR SYSERR +@010 LDX #KYBDDSBL + STX E_IER + STY KEYCNT + STY BUFHEAD + STY BUFTAIL + STA BUFSIZ + LDX #KYBDENBL + STX E_IER + RTS +; +CCNTL05 LDA E_IER ;5 -- Flush Buffer + PHA + LDA #KYBDDSBL + STA E_IER + STY KEYCNT + STY BUFHEAD + STY BUFTAIL + PLA + AND #KYBDENBL + ORA #BITON7 + STA E_IER + RTS +; +CCNTL06 PHP ;6 -- Attention Event + SEI + LDY #5 +@010 LDA (SCLIST),Y + STA ATTNEVNT,Y + DEY + BPL @010 + PLP + RTS +; +CCNTL08 PHP ;8 -- Any Key Event + SEI + LDY #4 +@010 LDA (SCLIST),Y + STA ANYKYEVNT,Y + DEY + BPL @010 + PLP + RTS +; +CCNTL10 = * ;10 -- No Wait Input + AND #BITON7 + STA NOWAIT + RTS +; +CCNTL11 = * ;11 -- Screen Echo + AND #BITON7+BITON6 + STA ECHO + RTS +; +CCNTL12 = * ;12 -- Character Copy + AND #BITON7 + STA CHCPYFLG + RTS +; +CCNTL13 = * ;13 -- Character Delete + AND #BITON7+BITON6 + STA CHDELFLG + RTS +; +CCNTL14 = * ;14 -- Line Delete + AND #BITON7+BITON6 + STA LNDELFLG + RTS +; +CCNTL15 = * ;15 -- Escape Functions + AND #BITON7 + STA ESCAPE + RTS +; +CCNTL18 = * ;18 -- Restore contents of viewport + BIT DSPLYCTL + BMI @020 + INY + EOR HMODE + BMI @010 + LDA (SCLIST),Y + CMP VPHMAX + BNE @010 + INY + LDA (SCLIST),Y + CMP VPVMAX + BNE @030 + LDA #$80 + JMP SCRNDUMP +; +@010 LDA (SCLIST),Y + INY + ORA (SCLIST),Y + BNE @030 +@020 RTS +; +@030 LDA #XCTLPARM + JSR SYSERR + +; .PAGE +;---------------------------------------------------------------------- +; +; Subroutine LOADCHR +; +; This subroutine is called to load an ASCII code and a character +; image into one of the character download cells in the text pages. +; +; LOADCHR requires four bytes of zero page storage for pointers. In +; order to make it callable from either a device handler or an +; interrupt processor, all zero page references are indexed by X. +; On entry, the X register must contain the zero page offset to the +; character image pointer. The two bytes following the image +; pointer are used to address the download locations in the text +; page. +; +; Input Parameters: +; DNLDCEL -- character download cell number: [0,7] +; DNLDCHR -- ASCII character code: [0,7F] +; X reg -- zero page offset to pointers +; (0,X) image pointer set by caller +; (2,X) download cell pointer set by LOADCHR +; +; On exit, DNLDCEL, DNLDCHR, and X will be unchanged. The image +; pointer will have been incremented by eight. A and Y are destroyed. +; +;---------------------------------------------------------------------- +; +DIMGPTR = 00 ;Zero page pointer to image +DCELPTR = 02 ;Zero page pointer to cell +; +LOADCHR = * + LDY #00 ;Use Y for row counter +@010 LDA DNLDCEL ;Set up cell pointer + AND #03 ; for ASCII code + ORA DCPTRL,Y + STA DCELPTR,X + LDA DNLDCEL + LSR A + LSR A + CPY #04 + ROL A + ORA #08 + STA DCELPTR+1,X + LDA DNLDCHR ;Store ASCII code into + STA (DCELPTR,X) ; download cell + LDA DCELPTR+1,X ;Fix cell pointer + EOR #$0C ; for character image + STA DCELPTR+1,X + LDA (DIMGPTR,X) ;Store character image + STA (DCELPTR,X) ; into download cell + INC DIMGPTR,X ;Increment the image pointer + BNE @020 + INC DIMGPTR+1,X +@020 INY ;Increment the row number + CPY #08 + BCC @010 ;Not done yet + RTS +; +DCPTRL = * ;Table of download cell addresses + .BYTE $78,$7C,$F8,$FC + .BYTE $78,$7C,$F8,$FC +; .PAGE +;---------------------------------------------------------------------- +; +; Subroutine DNLDINT +; +; This subroutine processes the VBL interrupt that signals the +; completion of a character download cycle. If the REQUEST bit of +; DNLDFLG is set, another RES of eight characters will be +; downloaded; otherwise, the CB1 and CB2 resources will be +; released and the ACTIVE bit will be cleared. DNLDINT assumes +; that the X register points to a four byte area on the zero page +; that can be used for LOADCHR. +; +;---------------------------------------------------------------------- +; +DNLDINT = * + BIT DNLDDSBL ;Disable download + LDA #VBLDSBL + STA E_IER ;Mask VBL interrupts + BIT DNLDFLG ;Test REQUEST bit + BVC @030 + CLI ;Enable interrupts + LDA #07 + STA DNLDCEL ;Start with cell 7 + LDA DNLDIMG + STA DIMGPTR,X ;Set up IMAGE pointer + LDA DNLDIMG+1 + STA DIMGPTR+1,X +@010 JSR LOADCHR ;Load one character image + INC DNLDCHR ;Bump character code + BPL @020 + ASL DNLDFLG ;Clear REQUEST bit +@020 DEC DNLDCEL ;Bump cell number + BPL @010 ;More to do + LDA DIMGPTR,X + STA DNLDIMG ;Save IMAGE pointer + LDA DIMGPTR+1,X + STA DNLDIMG+1 + JMP DNLD_GO ;Enable downloading +; +@030 ASL DNLDFLG ;Clear ACTIVE bit + LDA #DNLDSSIZ + LDX DNLDSADR + LDY DNLDSADR+1 + JSR DEALCSIR ;Deallocate SIRs + RTS +; .PAGE +;---------------------------------------------------------------------- +; +; Subroutine GETSIRS +; +; This subroutine allocates SIRs 5 & 6 and initializes them to +; monitor VBL for character downloading. If the SIRs can not be +; allocated, it sets an error code and returns directly to the +; dispatcher. +; +;---------------------------------------------------------------------- +; +GETSIRS = * + BIT DNLDFLG ;Wait for any previous + BMI GETSIRS ; request to finish + LDA #DNLDSSIZ + LDX DNLDSADR + LDY DNLDSADR+1 + JSR ALLOCSIR + BCS @010 + PHP + SEI + LDA E_PCR ;Set CB1 to monitor VBL + AND #$0F ; negative edge and + ORA #$60 ; CB2 to monitor + STA E_PCR ; positive edge + LDA #VBLDSBL + STA E_IER + PLP + RTS +; +@010 PLA ; pull caller's + PLA ; address, and + LDA #XNORESRC ; return to dispatcher + JSR SYSERR ; with an error +; .PAGE +;---------------------------------------------------------------------- +; +; Subroutine LOADSET +; +; This subroutine is called to initiate downloading of the entire +; text screen character set. LOADSET calls GETSIRS to set up the +; 6522 to monitor VBL and interrupt on the negative edge. It then +; copys the character set to the screen's local data area, sets the +; request bit, and enables the VBL interrupt. The VBL interrupt +; processor, DNLDINT, will complete the actual downloading. +; +; Parameters: +; SCLIST: Pointer to caller's 1024 byte character set +; +; Zero Page Temporary Storage: +; WORK1: Pointer to system's character set +; +;---------------------------------------------------------------------- +; +LOADSET = * + JSR GETSIRS + LDA #TEXTCSA ;/$100 + STA WORK1+1 + STA DNLDIMG+1 + LDA #ASC_NUL + STA DNLDCHR + LDX #4 ;Set X to move 4 pages + LDY #0 ;Set Y to move full page + LDA SCLIST+1 + CMP #$FB + BCC @010 + SBC #$80 ;Adjust address to avoid + STA SCLIST+1 ; bank wrap around + INC $1400+SCLIST+1 +@010 LDA (SCLIST),Y ;Copy character set to + STA (WORK1),Y ; text char set buffer + INY + BNE @010 + INC SCLIST+1 + INC WORK1+1 + DEX + BNE @010 + LDA #$C0 ;Set download active + STA DNLDFLG ; and request flags + LDA #VBLENBL + STA E_IER ;Enable interrupts in VBL neg + RTS +; .PAGE +;---------------------------------------------------------------------- +; +; Subroutine LOAD8 +; +; This subroutine is called to download up to eight text character +; images. LOAD8 calls GETSIRS to set up the 6522 to monitor VBL +; and interrupt on the negative edge. It then loads the character +; images into the screen's download cells and enables downloading +; and the VBL interrupt. The download operation is completed by +; the interrupt processor DNLDINT. +; +; Parameters: +; SCLIST: Pointer to caller's character sets +; +; Zero Page Temporary Data: +; COUNT: Number of characters to download +; WORK1: Pointer to character image for LOADCHR +; WORK2: Work area for LOADCHR +; +;---------------------------------------------------------------------- +; +LOAD8 = * + CMP #01 ;Check download count + BCS @010 + RTS +; +@010 CMP #09 + BCC @020 + LDA #XCTLPARM ;Too many + JSR SYSERR +; +@020 STA COUNT + JSR GETSIRS +; + INC SCLIST ;Bump list address + BNE @030 ; to first character + INC SCLIST+1 +; +@030 LDA #08 + STA DNLDCEL +; +@040 LDY #00 + LDA (SCLIST),Y ;Get character code + STA DNLDCHR + INC SCLIST ;Bump list address + BNE @050 ; to character image + INC SCLIST+1 +; +@050 LDA #03 + STA WORK1+1 + LDA DNLDCHR + ASL A + ASL A + ROL WORK1+1 ;Set up address of character + ASL A ; image in C00 to FFF space + ROL WORK1+1 + STA WORK1 +; + LDY #07 +@060 LDA (SCLIST),Y ;Copy character image + STA (WORK1),Y ; to C00 image space + DEY + BPL @060 +; + DEC DNLDCEL + LDX #WORK1 + JSR LOADCHR ;Download this character +; + LDA DNLDCEL + CMP COUNT + BCS @050 ;Do same character again + LDA #08 + ADC SCLIST ;Bump list address + STA SCLIST ; to next character + BCC @070 + INC SCLIST+1 +@070 DEC COUNT + BNE @040 +; + LDA #$80 ;Set download active + STA DNLDFLG +DNLD_GO BIT DNLDENBL + LDA #VBLCLR + STA E_IFR ;Clear both VBL flags +@080 BIT E_IORB ;Check composite blanking + BVC @090 + BIT E_IFR ;Check VBL flags + BEQ @080 +@090 STA E_IFR ;Clear VBL flags + LDA #VBLENBL ;Enable VBL interrupt + STA E_IER + RTS + +; .PAGE +;---------------------------------------------------------------------- +; +; Console Open Request +; +;---------------------------------------------------------------------- +; +CNSLOPEN = * + BIT OPENFLG ;Console open? + BPL @010 ; No + LDA #XNOTAVIL + JSR SYSERR +; +@010 LDA #KYBDSSIZ ;Allocate the keyboard interrupt + LDX KYBDSADR + LDY KYBDSADR+1 + JSR ALLOCSIR + BCS @020 + LDA #TRUE + STA OPENFLG ;Set console open + JSR CCNTL00 ;Reset console parameters + PHP + SEI + LDA E_PCR + AND #$F1 + ORA #02 ;Set up keyboard interrupt + STA E_PCR + PLP + LDA #KYBDCLR + STA E_IFR ;Clear keyboard flag + BIT KYBDSTRB ;Clear the keyboard strobe + LDA #KYBDENBL + STA E_IER ;Unmask keyboard interrupts + CLC + RTS +; +@020 LDA #XNORESRC ;Couldn't get keyboard resource + JSR SYSERR +; .PAGE +;---------------------------------------------------------------------- +; +; Console Close Request +; +;---------------------------------------------------------------------- +; +CNSLCLOS = * + ASL OPENFLG ;Console open? + BCS @010 ; Yes + JMP CNOTOPEN +; +@010 BIT DNLDFLG ;Wait for pending download + BMI @010 + LDA #KYBDDSBL + STA E_IER ;Mask keyboard interrupts + BIT KYBDSTRB ;Clear the keyboard strobe + LDA #KYBDSSIZ + LDX KYBDSADR + LDY KYBDSADR+1 + JSR DEALCSIR ;Deallocate the keyboard interrupt + RTS +; .PAGE +;---------------------------------------------------------------------- +; +; Console Initialization Request +; +;---------------------------------------------------------------------- +; +CNSLINIT = * + LDA #FALSE + STA OPENFLG + LDA B_REG ;Set bank register for + STA KYBDBANK ; keyboard and download + STA DNLDBANK ; interrupt handlers + LDA #TEXTCSA ;/$100 + STA SCLIST+1 + LDA #00 + STA $1400+SCLIST+1 + JSR LOADSET + CLC + RTS + +; .PAGE +;---------------------------------------------------------------------- +; +; Subroutine VERIFY +; +; This subroutine checks the screen's hardware mode, software mode, +; and viewport parameters for self consistency. It also sets the +; screen switches and the following internal variables: +; HMODE, SMINV, SMCURSOR, SMSCROLL, SMAUTOCR, SMAUTOLF, +; SMAUTOADV, VPHMAX, VPVMAX, and TCOLOR +; +; Parameters: none +; +; Exit: +; A, X, Y: Undefined +; +;---------------------------------------------------------------------- +; +VERIFY = * + LDA HMODE ;Validate HMODE + AND #03 ; and set 80 column + ASL A ; flag in bit 7 + CMP #04 + BCC @010 + LDA #04 +@010 ROR A + STA HMODE + LDY SMODE ;Preserve SMODE + LDA #00 + LDX #5 +@020 STA SMFLAGS,X + LSR SMODE ;Set SMODE flags + ROR SMFLAGS,X + DEX + BPL @020 + STY SMODE + LDA #79 + BIT HMODE ;Screen width := If 80 column, + BMI @100 ; then 79. + LDA #39 ; else 39. +@100 CMP VPR ;VPR <= Screen width + BCS @110 + STA VPR +@110 LDA VPR + CMP VPL ;VPL <= VPR + BCS @120 + STA VPL +@120 SEC + LDA VPR ;VPHMAX := + SBC VPL ; VPR - VPL + STA VPHMAX + CMP TPX ;TPX <= VPHMAX + BCS @200 + STA TPX +@200 LDA #23 + CMP VPB ;VPB <= Screen height + BCS @210 + STA VPB +@210 LDA VPB + CMP VPT ;VPT <= VPB + BCS @220 + STA VPT +@220 SEC + LDA VPB ;VPVMAX := + SBC VPT ; VPB - VPT + STA VPVMAX + CMP TPY ;TPY <= VPVMAX + BCS @300 + STA TPY +@300 LDA TCB + AND #$0F ;TCB=TCB MOD 16 + STA TCB + LDA TCF + AND #$0F ;TCF=TCF MOD 16 + STA TCF + ASL A + ASL A + ASL A ;SET TCOLOR := + ASL A + ORA TCB ;TCF * 16 + TCB + STA TCOLOR + PHP + SEI + LDA SCRNMODE ;Check screen mode + ASL A + BMI @500 ; Graphics + LDA E_REG + ORA #BITON5 + BCS @400 + AND #BITOFF5 +@400 STA E_REG + LDA HMODE + AND #03 + BCC @410 + ORA #BITON7 +@410 STA SCRNMODE ;Set screen mode + LSR A + AND #01 + TAY + LDA #00 + ROL A + TAX + LDA VMODE0,X ;B&W / Color + LDA VMODE1,Y ;40 / 80 Column + BIT VMODE2 ;Page 1 always + BIT VMODE3 ;Text of course +@500 PLP + JSR TBASCAL ;New base addr. + RTS +; .PAGE +;---------------------------------------------------------------------- +; +; Subroutine CURSOR +; +; This subroutine displays or removes the cursor by inverting the +; character at the current cursor position. +; +; Parameters: none +; +; Exit: +; A, X, Y: Undefined +; +;---------------------------------------------------------------------- +; +CURSOR = * + BIT SMCURSOR ;is cursor enabled? + BPL @020 ;if not, exit + LDA TPX + BIT HMODE + BPL @010 ;40 col: X=TPX + LSR A ;80 col: X=TPX/2 + BCC @010 + TAY + LDA (BASE2),Y ;get character + EOR #$80 ;and invert it + STA (BASE2),Y ;put it back + RTS +@010 TAY + LDA (BASE1),Y ;get character + EOR #$80 ;and invert it + STA (BASE1),Y ;put it back +@020 RTS +; .PAGE +;---------------------------------------------------------------------- +; +; Single Character Screen Read (Console character copy) +; +; This subroutine returns the character at the current cursor position. +; +; Parameters: none +; +; Exit: +; A: character +; X, Y: Undefined +; +; +;---------------------------------------------------------------------- +; +SCRNPICK = * + LDA TPX + TAY + BIT HMODE + BPL @010 ;40 Col -- Y := TPX + LSR A ;80 Col -- Y := TPX/2 + TAY + BCC @010 + LDA (BASE2),Y ;Read odd text page + BCS @020 +@010 LDA (BASE1),Y ;Read even text page +@020 RTS +; .PAGE +;---------------------------------------------------------------------- +; +; Subroutine TBASCAL -- Text Base Address Calculator +; +; This subroutine sets the base address registers, BASE1 and BASE2, +; to point to the current line in screen memory. BASE1 always points +; to column 0 of the current viewport while BASE2 points to column 1. +; +; Entry TBASCAL: +; Parameters: none +; +; Entry TBASCAL1: +; Parameters: +; X: Absolute screen line number +; +; Exit (either entry point): +; A: Undefined +; X: Absolute screen line number +; Y: Unchanged +; +;---------------------------------------------------------------------- +; +TBASCAL = * + CLC + LDA TPY ;vertical position + ADC VPT ; + viewport top + TAX +TBASCAL1 = * + CLC + LDA VPL ;viewport left: + BIT HMODE + BPL @010 ;if 80 column mode, + LSR A ;then divide by two +@010 PHP + ADC BASL,X ;base address (LO) + STA BASE1 ;same for both pages + STA BASE2 + LDA BASH,X ;base address (HI) + PLP + BCC @020 + DEC BASE1 ;Odd window adjustment + EOR #$0C +@020 STA BASE1+1 ;even page address + EOR #$0C + STA BASE2+1 ;odd page address + RTS +; .PAGE +;---------------------------------------------------------------------- +; +; Subroutine CLREOL -- Clear to End of Line +; +; This subroutine clears the current line from the current cursor +; position to the end of the line. The starting position may be +; passed in Y using the CLREOL1 entry point. The text base address +; pointers, BASE1 and BASE2, must point to the current line. +; +; Entry CLREOL: +; Parameters: none +; +; Entry CLREOL1: +; Parameters: +; Y: Starting horizontal position +; +; Zero Page Temporary Storage: +; BLANK, TEMPX +; +; Exit (either entry point): +; A, Y: Undefined +; X: Preserved +; +;---------------------------------------------------------------------- +; +CLREOL = * + LDY TPX ;horizontal position +CLREOL1 = * + LDA #$80+ASC_SP ;Set up a blank + EOR SMINV + STA BLANK + BIT HMODE + BPL @200 + TYA + BNE @150 +; +; 80 column clear full line +; + LDA VPHMAX ;Start at right edge + LSR A + TAY + LDA BLANK ;Load the blank + BCC @110 +@100 STA (BASE2),Y ;Clear odd column +@110 STA (BASE1),Y ; then even column + DEY + BPL @100 ;Repeat to BOL + RTS +; +; 80 column clear to end of line +; +@150 STX TEMPX ;Save X + CLC + SBC VPHMAX ;Calculate negative number + TAX ; of bytes to blank + TYA + LSR A + TAY + LDA BLANK ;Load the blank + BCS @170 +@160 STA (BASE1),Y + INX + BPL @180 +@170 STA (BASE2),Y + INY + INX + BMI @160 +@180 LDX TEMPX ;Restore X + RTS +; +; 40 column clear to end of line +; +@200 LDA BLANK + STA (BASE1),Y + LDA TCOLOR + STA (BASE2),Y + CPY VPHMAX + INY + BCC @200 + RTS + +; .PAGE +;---------------------------------------------------------------------- +; +; Subroutine CLREOS -- Clear to End of Screen +; +; This subroutine clears the screen from the current cursor position +; to the end of the viewport. The CLREOS1 entry allows the line number +; to be passed in X and the starting column number in Y. +; +; Entry CLREOS: +; Parameters: none +; +; Entry CLREOS1: +; Parameters: +; X: Starting absolute line number +; Y: Starting column number +; +; Exit: +; A, X, Y: Undefined +; +;---------------------------------------------------------------------- +; +CLREOS = * + CLC + LDA TPY + ADC VPT + TAX ;Get starting line number + LDY TPX ;Get starting cursor position +CLREOS1 = * +@010 JSR TBASCAL1 + JSR CLREOL1 ;Clear this line + LDY #0 ;Reset starting column + CPX VPB + INX + BCC @010 + JMP TBASCAL ;Reset base address +; .PAGE +;----------------------------------------------------------------------- +; +; Scroll Text Viewport +; +; This subroutine scrolls the text within the viewport up or down by +; one line. On entry, A must contain an UP/DOWN flag ( $00 => UP, +; $80 => DOWN ). +; +; Parameters: +; A: Up / Down flag +; +; Zero Page Temporary Storage: +; WORK1, WOR2: Screen pointers +; FLAGS: Bit 7 -- even / odd flag for scroll loop +; Bit 6 -- up / down flag +; TEMP1: Starting Y index for scroll loop +; +; Subroutines called: +; TBASCAL1, CLREOL1 +; +; Exit: +; A, X, Y: Undefined +; +;----------------------------------------------------------------------- +; +SCROLL = * + STA FLAGS ;Save UP/DOWN flag + SEC + LDA VPHMAX + BIT HMODE + BPL @010 + LSR A +@010 STA TEMP1 ;Get starting loop index + ROR FLAGS ;Save even/odd flag + LDX VPT + BIT FLAGS + BVC @020 + LDX VPB +@020 JSR TBASCAL1 ;Get starting base addresses +; +@030 BIT FLAGS + BVC @040 + CPX VPT ;Scroll down + BEQ @080 ; All done + DEX ; Go up one line + BPL @050 +@040 CPX VPB ;Scroll up + BEQ @080 ; All done + INX ; Go down one line +; +@050 LDA BASE1 + LDY BASE1+1 ;Copy source address + STA WORK1 ; to destination address + STY WORK1+1 + LDA BASE2 + LDY BASE2+1 + STA WORK2 + STY WORK2+1 + JSR TBASCAL1 ;Get next source address + LDY TEMP1 + BIT FLAGS + BPL @070 +@060 LDA (BASE2),Y ;Scroll this line + STA (WORK2),Y ; move odd column +@070 LDA (BASE1),Y ; move even column + STA (WORK1),Y + DEY + BPL @060 + BMI @030 +; +@080 LDY #0 + JSR CLREOL1 ;Clear last line + JMP TBASCAL +; .PAGE +;----------------------------------------------------------------------- +; +; Horizontal Shift +; +; This subroutine shifts the text within the viewport left or right. +; On entry, A must contain an eight bit signed shift offset, negative +; for left shifts and positive for right shifts. +; +; Parameters: +; A: Signed shift offset +; +; Zero Page Temporary Storage: +; BLANK, TEMPX +; WORK1, WORK2: Screen pointers +; FLAGS: Bit 7 -- right / left flag +; Bit 6 -- odd / even flag for shift right +; TEMP1: Positive shift offset +; TEMP2: Absolute shift column +; TEMP3: shift right -- starting shift index +; shift left -- shift count +; TEMP4: shift right -- starting clear index +; shift left -- column for clear +; +; Subroutines Called: +; CLREOS1, CLREOL1 +; +; Exit: +; A, X, Y: Undefined +; +;----------------------------------------------------------------------- +; +SHIFT = * + TAY + BEQ @020 ;Nothing to do + AND #BITON7 + STA FLAGS ;Set right / left flag + TYA + CMP #$80 + BCC @010 + EOR #$FF ;Make shift count positive +@010 ADC #00 + STA TEMP1 ;Absolute shift offset + ADC VPL ;Absolute column number + STA TEMP2 ; for base address + LDX VPT + SEC + LDA VPHMAX + SBC TEMP1 + BCS @030 + LDY #00 ;Shift entire viewport + JSR CLREOS1 +@020 RTS +@030 BIT FLAGS + BMI @060 +; + SEC ;Set up for shift right + BIT HMODE + BPL @040 + LSR A +@040 STA TEMP3 ;Set starting index for shifting + LDA #BITON6 + BCS @050 + LDA #00 +@050 ORA FLAGS ;Set odd / even flag + STA FLAGS + LDY TEMP1 + DEY + STY TEMP4 ;Set index for clearing + LDA #$80+ASC_SP + EOR SMINV + STA BLANK ;Set up space character + JMP SHIFT1 +; +@060 TAY ;Set up for shift left + BIT HMODE + BMI @070 + SEC + ROL A +@070 STA TEMP3 ;Set count for shifting + INY + STY TEMP4 ;Set index for clearing +; +SHIFT1 JSR TBASCAL1 ;Get base address + CLC + LDA TEMP2 + BIT HMODE + BPL @010 + LSR A +@010 PHP + ADC BASL,X + STA WORK1 ;Get shifted base address + STA WORK2 + LDA BASH,X + PLP + BCC @020 + DEC WORK1 + EOR #$0C +@020 STA WORK1+1 + EOR #$0C + STA WORK2+1 + BIT FLAGS + BMI SHFTLF +; +SHFTRT LDY TEMP3 ;Shift this line right + BVC @020 +@010 LDA (BASE2),Y + STA (WORK2),Y +@020 LDA (BASE1),Y + STA (WORK1),Y + DEY + BPL @010 + LDA TEMP4 ;Clear beginning of line + BIT HMODE + BPL @050 + LSR A + TAY + LDA BLANK + BCC @040 +@030 STA (BASE2),Y +@040 STA (BASE1),Y + DEY + BPL @030 + BMI SHIFT2 +@050 TAY +@060 LDA BLANK + STA (BASE1),Y + LDA TCOLOR + STA (BASE2),Y + DEY + BPL @060 +; +SHIFT2 CPX VPB + INX ;Go to next line + BCC SHIFT1 + JMP TBASCAL +; +SHFTLF LDY #00 ;Shift this line left + STX TEMPX + LDX TEMP3 ;Get shift count +@010 LDA (WORK1),Y + STA (BASE1),Y + DEX + BMI @020 + LDA (WORK2),Y + STA (BASE2),Y + INY + DEX + BPL @010 +@020 LDX TEMPX + LDY TEMP4 + JSR CLREOL1 + JMP SHIFT2 +; .PAGE +;----------------------------------------------------------------------- +; +; Dump and Restore Contents of Viewport +; +; This subroutine will dump or restore the contents of the viewport to +; or from the caller's buffer. On entry, A must contain a dump/restore +; flag. ($00 => Dump $80 => Restore) +; +; Parameters: +; A: Dump / Restore flag +; +; Zero Page Temporary Storage: +; WORK1, WORK2: Extended pointers to caller's buffer +; FLAGS: Bit 7 -- odd / even move count flag +; Bit 6 -- dump / restore flag +; TEMP1: Starting move index +; TEMP2: Move count +; +; Exit: +; A, X, Y: Undefined +; +;----------------------------------------------------------------------- +; +SCRNDUMP = * + STA FLAGS + JSR CURSOR ;Turn cursor off + LDA VPHMAX + STA TEMP2 + INC TEMP2 + BIT HMODE + BMI @010 + ASL TEMP2 + ASL A +@010 LSR A + STA TEMP1 + ROR FLAGS + CLC + LDA SCLIST + ADC #03 ;Set work pointers to + STA WORK1 ; to caller's buffer + LDA SCLIST+1 + ADC #00 + CMP #$F0 + LDX $1401+SCLIST + BCC @020 + SBC #$80 ;Adjust extended address + INX +@020 STA WORK1+1 + STX $1401+WORK1 + LDA TEMP2 + LSR A + ADC WORK1 + STA WORK2 + LDA WORK1+1 + ADC #00 + STA WORK2+1 + STX $1401+WORK2 +; +; Copy the contents of the window +; + LDX VPT +@100 JSR TBASCAL1 + LDY TEMP1 + BIT FLAGS + BVS @120 +; + BPL @115 +@110 LDA (BASE2),Y + STA (WORK2),Y +@115 LDA (BASE1),Y + STA (WORK1),Y + DEY + BPL @110 + BMI @140 +; +@120 BPL @135 +@130 LDA (WORK2),Y + STA (BASE2),Y +@135 LDA (WORK1),Y + STA (BASE1),Y + DEY + BPL @130 +; +@140 CLC + LDA WORK1 + ADC TEMP2 + STA WORK1 + BCC @150 + INC WORK1+1 +@150 CLC + LDA WORK2 + ADC TEMP2 + STA WORK2 + BCC @160 + INC WORK2+1 +@160 CPX VPB + INX + BCC @100 +; + JSR TBASCAL + JSR CURSOR ;Restore cursor + RTS +; .PAGE +;---------------------------------------------------------------------- +; +; ZPOUT +; +; This subroutine saves the driver's zero page data. +; +;---------------------------------------------------------------------- +; +ZPOUT LDX #ZPLENGTH-1 ;Zero Page save area length +@010 LDA ZPDATA,X + STA ZPSAVE,X + DEX + BPL @010 + RTS + + .ENDPROC diff --git a/drivers/grafix/README.md b/drivers/grafix/README.md new file mode 100644 index 0000000..6dbd891 --- /dev/null +++ b/drivers/grafix/README.md @@ -0,0 +1,3 @@ +# Apple /// grafix driver + +This is updated from a disassembly by Erik Olbrys that was included in the Three's Company BBS files on the A3 dvd diff --git a/drivers/grafix/grafix.s b/drivers/grafix/grafix.s new file mode 100644 index 0000000..a8769a8 --- /dev/null +++ b/drivers/grafix/grafix.s @@ -0,0 +1,2412 @@ +;============================================================== +;SOS GRAPHICS DRIVER +;(C) Apple Computer, Inc., 1983 v1.3 +; - edited 3/24/86 to 8/31/86 by Erik Olbrys CIS 71236,1245 +;============================================================== + + .feature labels_without_colons + .setcpu "6502" + .reloc +; +;driver comment field +;this is put in the TEXT segment so we can get the lenght and output it ok +; + .segment "TEXT" + .word $FFFF ;Comment follows.. + .word $0039 ;$39 bytes long + .byte "Copyright (C) 1983 Apple Computer, Inc. Graphics Driver." + +; +;Driver code part +;this is put in the DATA segement +; + + .segment "DATA" + +DEVTYPE = $62 ;Character device, read/write +SUBTYPE = $01 ;Device subtype +MANID = $01 ;Manufacturer ID - Apple Inc. +RELEASE = $1300 ;Release number in BCD format + +;------------------- +;N-WAY SWITCH MACRO +;SWITCH [index], [bounds], adrs_table, [*] +;------------------- + + .MACRO SWITCH index,bounds,adrs_table ;,noexec ;See SOS Reference + .IFNBLANK index ;If PARM1 is present, + LDA index ; load A with switch index + .ENDIF + .IFNBLANK bounds ;If PARM2 is present, + CMP #bounds+1 ; perform bounds checking + BCS @110 ; on switch index + .ENDIF + ASL A ;Multiply by 2 for table index + TAY + LDA adrs_table+1,Y ;Get switch address from table + PHA ; and push onto Stack + LDA adrs_table,Y + PHA +; .IF noexec <> "*" ;If PARM4 is omitted, + RTS ; exit to code +; .ENDIF +@110 .ENDMACRO + +;-------------------- +;INCREMENT WORD MACRO +;-------------------- + + .MACRO INW inword + INC inword ;Increment low-order + BNE @210 ;If 'Carry', + INC inword+1 ; increment high-order +@210 .ENDMACRO + +;------------------------------ +;INCREMENT 3-BYTE ADDRESS MACRO +;------------------------------ + + .MACRO INCADR addr + INC addr + BNE @310 + INC addr+1 + BNE @310 ;Bank overflow? + LDX #$80 ;Yes + STX addr+1 + INC addr+1+$1400 ;Increment X-byte +@310 .ENDMACRO + + .PROC GRAFIX + +;--------------- +;GENERAL EQUATES +;--------------- + +TRUE = $80 +FALSE = $00 +BITON0 = $01 +BITON1 = $02 +BITON2 = $04 +BITON3 = $08 +BITON4 = $10 +BITON5 = $20 +BITON6 = $40 +BITON7 = $80 + +;----------------------------- +;SOS GLOBAL DATA & SUBROUTINES +;----------------------------- + +SCR_MODE = $1906 +MEM_FLAG = $1907 ;amount of mem reserved for grafix +SYSERR = $1928 ;report error to system + +;---------------------------- +;SOS DEVICE HANDLER INTERFACE +;---------------------------- + +SOSINT = $C0 +REQCODE = SOSINT+0 ;SOS request code +BUFFER = SOSINT+2 ;Buffer pointer +REQCNT = SOSINT+4 ;Requested count/byte count +CTLSTAT = SOSINT+2 ;Control/status code +CSLIST = SOSINT+3 ;Control/status list pointer +RETPTR = SOSINT+8 ;Returned count pointer + +;-------------------- +;HARDWARE I/O ADDRESS +;-------------------- + +SETBW = $C050 ;black & white on +SETCOL = $C051 ;color on +COLM40 = $C052 ;set 40 columns +COLM80 = $C053 ;set 80 columns +LOWSCR = $C054 ;set page one +HISCR = $C055 ;set page two +TEXT = $C056 ;set text mode +HIRES = $C057 ;set hires grafix mode + +;--------------- +;SOS ERROR CODES +;--------------- + +XREQCODE = $20 ;invalid request code +XCTLCODE = $21 ;invalid control/status code +XCTLPARAM = $22 ;invalid control/status param +XNOTOPEN = $23 ;device not open +XNOTAVAIL = $24 ;device not available +XNORESRC = $25 ;resource not available +XBADOP = $26 ;invalid operation +XBADMEM = $30 ;insufficient amount of memory alocated + +;----------------- +;ZERO PAGE EQUATES +;----------------- + +ZPC9 = $C9 +ZPCA = $CA +ZPCB = $CB +ZPCC = $CC +ZPCD = $CD +ZPCE = $CE +ZPCF = $CF +ZPD0 = $D0 +ZPD1 = $D1 +ZPD2 = $D2 +ZPD3 = $D3 +ZPD4 = $D4 +ZPD5 = $D5 +ZPD6 = $D6 +ZPD7 = $D7 +ZPD8 = $D8 +ZPD9 = $D9 +ZPDA = $DA +ZPDB = $DB +ZPDC = $DC +ZPDD = $DD +ZPDE = $DE +ZPDF = $DF +ZPE0 = $E0 +ZPE1 = $E1 +ZPE2 = $E2 +ZPE3 = $E3 +ZPE4 = $E4 +ZPE5 = $E5 +ZPE6 = $E6 +ZPE7 = $E7 +ZPE8 = $E8 +ZPE9 = $E9 +ZPEA = $EA +ZPEB = $EB +ZPEC = $EC +ZPED = $ED +ZPEE = $EE +ZPEF = $EF +ZPF0 = $F0 +ZPF1 = $F1 +ZPF2 = $F2 +ZPF3 = $F3 +ZPF4 = $F4 +ZPF5 = $F5 +ZPF6 = $F6 +ZPF7 = $F7 +ZPF8 = $F8 +ZPF9 = $F9 +ZPFA = $FA +ZPFB = $FB +ZPFC = $FC +ZPFD = $FD +ZPFE = $FE +ZPFF = $FF + + +; --------------------------- +; Device Identification res +; --------------------------- + +DIB .word 0000 ; link + .word START ; entry point + .byte 07 ; name len + .byte ".GRAFIX " ; device name + .byte TRUE ; status -- active + .byte FALSE ; slot -- N/A + .byte 00 ; unit # + .byte DEVTYPE ; type + .byte SUBTYPE ; subtype + .byte 00 ; reserved for future use + .word 0000 ; # res s -- none + .word MANID ; man id -- Apple Inc. + .word RELEASE ; ver # -- 1.30 + +CNFBLK .word $0096 ; DCB length +DCB .byte $00 ;graphics mode + .byte $00 ;transfer mode + .word $0000 ;cursor x-position + .word $0000 ; y-position + .word $0000 ;viewport left edge + .word $0117 ; right edge:= 279. + .word $0000 ; bottom edge + .word $00BF ; top edge:= 191. + .byte $0F ;pencolor:= white + .byte $00 ;fillcolor:= black + .word $0C00 ;Character font address + .byte $00 ; address X-Byte + .byte $07 ;character cell bit width + .byte $08 ;character cell bit height + .byte $80 ; "Not currently used" (but it IS used) + +COLT2 .res 8,$00 ; Color operator table + .res 8,$11 + .res 8,$22 + .res 8,$33 + .res 8,$44 + .res 8,$55 + .res 8,$66 + .res 8,$77 + .res 8,$88 + .res 8,$99 + .res 8,$AA + .res 8,$BB + .res 8,$CC + .res 8,$DD + .res 8,$EE + .res 8,$FF + +DCB_LN = *-DCB + +L00F5 .res $0E,$00 ;some storage space + +; duplicate DCB -- used when restoring configuration + +CNTL_PARAM .byte $00 +GMODE .byte $00 ;graphics mode +XFMODE .byte $00 ;transfer mode +XPOS .word $0000 ;cursor x-position +YPOS .word $0000 ; y-position +VPORT_L .word $0000 ;viewport left edge +VPORT_R .word $0117 ; right edge = 279. +VPORT_B .word $0000 ; bottom edge +VPORT_T .word $00BF ; top edge = 191. +PN_COL .byte $0F ;pencolor = white +F_COL .byte $00 ;fillcolor = black +FONT .word $0C00 ;Character font address +FONT_XB .byte $00 ; address X-Byte +FWIDTH .byte $07 ;character cell bit width +FHEIGHT .byte $08 ;character cell bit height +NOT_USED .byte $80 ; "Not currently used" + +COL_TAB .res 8,$00 ; Color operator table + .res 8,$11 + .res 8,$22 + .res 8,$33 + .res 8,$44 + .res 8,$55 + .res 8,$66 + .res 8,$77 + .res 8,$88 + .res 8,$99 + .res 8,$AA + .res 8,$BB + .res 8,$CC + .res 8,$DD + .res 8,$EE + .res 8,$FF + + .byte "(C) 1980 Apple Computer" + +OPENFLG .byte 00 ;open/close flag +L01B2 .byte 00 ;base addr-hi temp +L01B3 .byte 00 ;alt base addr-hi temp +BYT_OFF .word 0008 ;byte offset of a font character +L01B6 .byte 00 ; \ +L01B7 .byte 00 ; bit pattern used +L01B8 .byte 00 ; in CLRVIEW +L01B9 .byte 00 ; / + +CHR_TEMP .byte 00 +CHR_INDX .byte 00 ;input buffer byte count +CHR_BUFF .res $20, 00 ;input buffer - copied from the D_WRITE buffer + +WIDTH_B .byte 01 ;byte width of font character + +L01DD .byte 00, 00, 00, 00, 00, 07, 00, 08, 00 +L01E6 .byte 00, 00 +L01E8 .byte 00 + +MVR_LO .byte $17, $17, $2F, $8B ;max viewport right, low byte (indexed) +MVT_LO .byte $BF ;max viewport top, low byte +MVR_HI .byte $01, $01, $02, $00 ;max viewport right, high byte +MVT_HI .byte $00 ;max viewport top, high byte + +L01F3 .byte 00, 00, 01, 01, 02, 02, 03, 03, 00, 00, 01 +L01FE .byte 01, 02, 02, 03, 03, 00, 00, 01, 01, 02, 02, 03, 03 + +L020B .byte $00,$80,$00,$80,$00,$80,$00,$80 ;base addr lo-byte, by y coord + .byte $28,$A8,$28,$A8,$28,$A8,$28,$A8 + .byte $50,$D0,$50,$D0,$50,$D0,$50,$D0 + +L0223 .byte $20,$20,$20,$20,$40,$60,$60,$60 ;base addr hi-byte, by GMODE + +;required-memory bits for gmodes 0..7 -- must be =< val in $1907 (MEM_FLAG) +; also doubles as alternate base-address_hi +REQD_MEM .byte $20,$40,$40,$40,$40,$80,$80,$80 + +L0233 .byte $00,$01,$1E,$60,$00,$07,$78 +L023A .byte $0F,$70,$00,$03,$3C,$40,$00,$0F,$0F + .byte $0F,$0F,$0F,$0F,$0F + .byte $01,$02,$04,$08,$10,$20,$40,$80 +L0250 .byte $15,$0E,$07,$00 +L0254 .byte $0E,$0E,$1C,$07 +L0258 .byte $03 +L0259 .byte $04 +L025A .byte $1C + +START SWITCH REQCODE, 8, REQSW + +BADREQ LDA #XREQCODE ;switch fell through - + JSR SYSERR ; Invalids request code error + +NOTOPEN LDA #XNOTOPEN ;Graphics driver not open error + JSR SYSERR + +REQSW = * ; dispatch table + .word D_READ-1 + .word D_WRITE-1 + .word D_STATUS-1 + .word D_CONTRL-1 + .word BADREQ-1 ;not implemented + .word BADREQ-1 ;not implemented + .word D_OPEN-1 + .word D_CLOSE-1 + .word D_INIT-1 + + +D_INIT LDA #FALSE + STA OPENFLG ;set it as closed + RTS + + +D_OPEN BIT OPENFLG ;is it already open? + BPL @1 + LDA #XNOTAVAIL ;yep -- it's not available, + JSR SYSERR ; complain, never returns + +@1 JSR CONT0 ;initilize device + LDA #TRUE ;set it as open + STA OPENFLG + RTS + + +D_CLOSE ASL OPENFLG ;close it + BCS @1 + JMP NOTOPEN ;but it's not open! complain +@1 RTS + + +D_STATUS BIT OPENFLG ;is it open? + BMI @1 + JMP NOTOPEN +@1 SWITCH CTLSTAT, 2, STATSW + +DST_ERR LDA #XCTLCODE ;invalid status code + JSR SYSERR + +STATSW .word STAT0-1 ;NOP + .word STAT1-1 ;preserve status table + .word STAT2-1 ;unknown + +STAT0 RTS ;nop + +STAT1 LDY #$00 ;preserve status table + LDA (CSLIST),Y + CMP #DCB_LN + BCS @3 + LDA #XCTLPARAM + JSR SYSERR +@3 LDA #DCB_LN + STA (CSLIST),Y + TAY +@4 LDA CNTL_PARAM,Y + STA (CSLIST),Y + DEY + BNE @4 + RTS + +STAT2 LDY #$00 ;Return newline status + LDA #$00 ; always =0, only satisfying the proper + STA (CSLIST),Y ; character count will terminate an input, + RTS ; as opposed to terminating at newline char + + +D_CONTRL BIT OPENFLG ;is it open? + BMI @1 + JMP NOTOPEN +@1 SWITCH CTLSTAT, 2, CNTLSW + +@2 JMP DST_ERR + +CNTLSW .word CONT0-1 ;Device reset + .word CONT1-1 ;Restore status table + .word CONT2-1 ;NOP + +CONT0 JSR L03A1 ;Reset + LDX #DCB_LN +@3 LDA CNFBLK+1,X + STA CNTL_PARAM,X + DEX + BNE @3 + JSR L03C9 + JSR L03BE + RTS + +CONT1 LDY #$00 ;Restore status table + LDA (CSLIST),Y + CMP #DCB_LN + BEQ @4 + LDA #XCTLPARAM + JSR SYSERR +@4 JSR L03A1 + LDY #DCB_LN +@5 LDA (CSLIST),Y + DEY + STA CNTL_PARAM+1,Y + BNE @5 + JSR L03C9 + JSR L03BE + RTS + +CONT2 RTS ;nop + + +D_READ BIT OPENFLG ;check if it's open + BMI @1 + JMP NOTOPEN + +@1 JSR L03A1 ;set up things + LDA XPOS+1 ;is XPOS<0000? + BMI @3 ; br if so + LDX ZPD5 ;is XPOS>MAX_VIEWPORT_RIGHT? + LDA MVR_LO,X + CMP XPOS + LDA MVR_HI,X + SBC XPOS+1 + BCC @3 ; br if so + LDA YPOS+1 ;is YPOS<0000? + BMI @3 ; br if so + LDA MVT_LO ;is YPOS>MAX_VIEWPORT_TOP? + CMP YPOS + LDA MVT_HI + SBC YPOS+1 + BCC @3 ; br if so + LDA YPOS + JSR CALCBASE ;calc base addr + LDA XPOS + LDY XPOS+1 + JSR CALCBYTE ;calc byte offset + JSR L10CB ;read color at pen position + ORA #$40 ;add 64 (it's within screen boundaries) +@2 LDY #$00 ;put char into read buffer + STA (BUFFER),Y + STY RETPTR+1 + INY + STY RETPTR ;RETPTR:=$0001 + JMP L03BE ;reset & leave +@3 LDA #BITON7 ;flag that pen is out of screen boundary + BNE @2 ;always + +L03A1 LDX #$0E ;setup things: restore stuff to zpage +@1 LDA L00F5,X + STA ZPCA,X + DEX + BPL @1 + LDX #$35 + LDA #$00 +@2 STA ZPC9+$1401,X + DEX + BPL @2 + LDA #$8F ;X-BYTE for graphics + STA ZPCA+$1401 + STA ZPCC+$1401 + RTS + +L03BE LDX #$0E ;reset things: save stuff from zpage +@1 LDA ZPCA,X + STA L00F5,X + DEX + BPL @1 + RTS + +; Verify Grafix parms (?) -- lots of jumps to here +L03C9 LDA GMODE ;filter and check out GRAFIXMODE + AND #$07 + STA GMODE + TAY + AND #$03 ;filter out page bit (page 1/page 2) + STA ZPD5 + TAX + LDA L0223,Y ;base addr hi-byte + STA L01B2 + LDA REQD_MEM,Y + STA L01B3 + LDA #$00 + STA L01E6 + STA L01E8 + LDA #$F0 + STA ZPD0 + + LDA F_COL ;check out FILL COLOR + ASL A + ASL A + ASL A + ASL A ;times 16 + ORA F_COL ;copies low nybble into hi nybble + PHA + BEQ @1 ;branch if fill color is black + CPX #$03 ;X-reg contains GMODE + BEQ @2 ;br if GMODE=3 (140x192 full color) + DEX + TXA + BEQ @1 + LDA #$FF +@1 LDX #$03 +@2 TAY + LSR A + STA L01B6,X + TYA + ROR A + TAY + DEX + BPL @2 + PLA + LDX ZPD5 + DEX + BNE @3 + STA L01B7 + STA L01B9 +@3 LDX #$00 + STX ZPD6 + STX ZPD7 + STX ZPD8 + + LDA XFMODE ;check out transfer mode + AND #$07 + STA XFMODE ;filter it + LSR A + ROR ZPD6 + LSR A + ROR ZPD6 + BIT ZPD6 + BVC @4 + BPL @4 + EOR #$01 +@4 LSR A + ROR ZPD7 + + LDA #$FF ;check out the color table + LDX #$7F +@5 LDY #$08 +@6 CMP COL_TAB,X + BNE @7 + DEX + DEY + BNE @6 + SEC + SBC #$11 + BCS @5 + BCC @8 ;always +@7 LDA ZPD7 + ORA #$40 + STA ZPD7 + +@8 LDA #$00 ;check out the font + LDX #$09 +@9 STA WIDTH_B,X ;width_b .. width_b+9 := 00 + DEX + BPL @9 + STA BYT_OFF ;set both to zero + STA BYT_OFF+1 + LDA FONT_XB + STA ZPD3+$1401 + LDA FONT+1 ;check if the font is the system font + CMP #$0C + BNE @10 ;is hi-byte = $0C?, br if not + LDA FONT_XB + BNE @10 ;is x-byte = $00, br if not + STA ZPD8 + BNE @11 ;never branches, why is this here? bug? + LDX #$07 ;it's the system font (00:0C00), set it up + STX FWIDTH ;width := 7 + INX + STX FHEIGHT ;height := 8 + JMP @11 +@10 LDA NOT_USED + STA ZPD8 +@11 LDX FWIDTH + BEQ @12 + DEX + TXA + LSR A + LSR A + LSR A + TAX + INX ;(FWIDTH-1) div 8 +1 + STX WIDTH_B ; width of font in bytes +@12 LDX FHEIGHT + BEQ @14 +@13 CLC ;calculate total # of bytes of + LDA WIDTH_B ; a single character + ADC BYT_OFF + STA BYT_OFF + LDA BYT_OFF+1 + ADC #$00 + STA BYT_OFF+1 + DEX + BNE @13 ;BYT_OFF=FHEIGHT * WIDTH_B + +@14 LDX #$06 ;check out the viewport definitions +L15 LDA VPORT_L+1,X + BPL @16 ;if it's negative, set it to zero + LDA #$00 + STA VPORT_L,X + STA VPORT_L+1,X ;set viewport left, right, top, bott := 0000 +@16 DEX + DEX + BPL L15 ;loop back + LDX #$06 + LDY #$04 +@17 LDA MVR_LO,Y ;is vport set beyond max size of the screen + CMP VPORT_L,X ; for this grafix mode? + LDA MVR_HI,Y + SBC VPORT_L+1,X + BCS @18 + LDA MVR_LO,Y ;Yes, so set it to the max allowed + STA VPORT_L,X + LDA MVR_HI,Y + STA VPORT_L+1,X +@18 DEX + DEX + BMI @19 + CPX #$04 + BCS @17 + LDY ZPD5 + BCC @17 +@19 LDX #$04 +@20 LDA VPORT_R,X + CMP VPORT_L,X + LDA VPORT_R+1,X + SBC VPORT_L+1,X ;check if left & right are reversed + BCS @21 ; branch if they're OK + LDY VPORT_L,X ; otherwise, turn them around the right way + LDA VPORT_R,X + STA VPORT_L,X + TYA + STA VPORT_R,X + LDY VPORT_L+1,X + LDA VPORT_R+1,X + STA VPORT_L+1,X + TYA + STA VPORT_R+1,X +@21 DEX + DEX + DEX + DEX + BPL @20 + BIT SCR_MODE + BVC @29 + BMI @22 + LDA L01FE ;;;;;L01FE this seems like a bug as these are absolute addresses! + AND #$DF + STA L01FE ;;;;;L01FE + JMP @29 +@22 LDA L01FE ;;;;;L01FE + ORA #$20 + STA L01FE ;;;;;L01FE + LDA SCR_MODE + LSR A + BCS @23 + BIT SETBW ;turn on the B&W mode + BCC @24 ; always +@23 BIT SETCOL ;turn on the color mode +@24 LSR A + BCS @25 + BIT COLM40 ;40 column mode + BCC @26 ; always +@25 BIT COLM80 ;80 column mode +@26 LSR A + BCS @27 + BIT LOWSCR ;page one + BCC @28 ; always +@27 BIT HISCR ;page two +@28 BIT HIRES ;turn on the graphics screen +@29 RTS + + +D_WRITE BIT OPENFLG ;but are we open? + BMI @1 ; br if open + JMP NOTOPEN + +@1 LDX GMODE + LDA MEM_FLAG ;memory allocation flag byte + CMP REQD_MEM,X ;see if proper amt of mem is allocated + BCS @2 ; br if OK + LDA #XBADMEM ;sorry, not enough memory for this mode + JSR SYSERR ; report the problem & leave + +@2 JSR L03A1 + LDA #$00 + STA RETPTR + STA RETPTR+1 + +@3 LDA RETPTR+1 ;check if all the chars in + CMP REQCNT+1 ; this DßWRITE call have been + BCC @4 ; carefully scrutinized. + LDA RETPTR + CMP REQCNT ; If all finished, jump out, otherwise + BCC @4 ; branch down a few bytes. + JMP L03BE + +@4 LDY #$00 + LDA (BUFFER),Y ;get the next character in the buffer + INCADR BUFFER ;increment the address pointer to the next byte + INW RETPTR ;increment the # of bytes handled + JSR @5 ;check out the current character + JMP @3 ;loop back for the next character + +@5 LDX CHR_TEMP + BEQ @7 ;br if a call is not currently being processed + LDY CHR_INDX ;load the index + STA CHR_BUFF-1,Y ;note: first byte stored at CHR_BUFF + INY ;incr index + TYA + CMP CALL_LEN,X ;Are all the bytes in this call present? + BCS @6 ; br if all present + STY CHR_INDX ;otherwise, store index, + RTS ; and get some more bytes + +@6 LDA CHR_TEMP ;all chars present, process call + LDY #$00 ; ...but first, reset some things + STY CHR_TEMP ; for the next time around + STY CHR_INDX ;clear index & temp + JMP CON_CHR ;now -- handle the call + +@7 CMP #$20 ;is it a control character? + BCC @8 ; br if so + JMP L0618 ;nope -- print the char onto the screen + +@8 TAX + LDA CALL_LEN,X ;get parm length for this call + BEQ @9 ; br if this isn't a valid call -- i.e. NOP + STX CHR_TEMP ;store the cntrl char here + CMP #$01 ;parm length=1? + BEQ @6 ; br if call doesn't have any parms (go to it!) + LDA #$01 + STA CHR_INDX ;initially put a one here -- used for indexing +@9 RTS + +; This list contains the total length (in bytes) of each control +; character call, including the control character itself. +; Ex.: chr(00) -- 0 bytes (nop) +; chr(03) -- 6 bytes (char_set) + +CALL_LEN .byte $00,$01,$09,$06,$0E,$00,$00,$00 ;chr( 0)..chr( 7) + .byte $00,$00,$01,$00,$00,$01,$01,$01 ;chr( 8)..chr(15) + .byte $02,$01,$06,$02,$02,$02,$00,$00 ;chr(16)..chr(23) + .byte $05,$05,$05,$00,$01,$00,$00,$00 ;chr(24)..chr(31) + +; set up to put a character on the graphics screen +L0618 CMP #$A0 + BCS @1 ; br is char >= $A0 + CMP #$80 + BCC @1 ; br if char < $80 + AND #$7F ;clear hi-bit +@1 LDX FWIDTH ;copy font info into temp locations + STX L01DD+5 + LDX FHEIGHT + STX L01DD+7 + LDX #$00 + STX L01DD+6 + STX L01DD+8 + LDX FONT ;copy font addrs into z-page locations + STX ZPD3 + LDX FONT+1 + STX ZPD4 + LDX FONT_XB + STX ZPD3+$1401 + TAX + BEQ @4 + +@2 CLC + LDA ZPD3 ;set up addr of font character + ADC BYT_OFF ;char_addr:= base_addr + (char# * byte_offset) + STA ZPD3 + LDA ZPD4 + ADC BYT_OFF+1 + STA ZPD4 + BCC @3 + INC ZPD3+$1401 + INC ZPD3+$1401 +@3 DEX + BNE @2 +@4 JSR PUTres ;put font char on screen + CLC ;update X & Y position after + LDA XPOS ; putting char on screen + ADC FWIDTH + STA XPOS + LDA XPOS+1 + ADC #$00 + STA XPOS+1 + RTS + +; Handle those control characters.... +CON_CHR SWITCH ,,CHARS + +CHARS .word CHR_NOP-1 + .word RSTVIEW-1 ;01 Reset Viewport + .word SETVIEW-1 ;02 Set Viewport + .word CHARSET-1 ;03 Character Set + .word DRAWBLK-1 ;04 Drawres + .word CHR_NOP-1 + .word CHR_NOP-1 + .word CHR_NOP-1 + .word CHR_NOP-1 + .word CHR_NOP-1 + .word MOV_PDN-1 ;10. Move Pen Down (LF) + .word CHR_NOP-1 + .word CHR_NOP-1 + .word RET_PEN-1 ;13. Return Pen (CR) + .word SCRNOFF-1 ;14. Turn Graphics Screen Off + .word SCRN_ON-1 ;15. Turn Graphics Screen On + .word SETMODE-1 ;16. Set Graphics Mode + .word RSTCOLT-1 ;17. Reset Color Operator Table + .word SETCOLT-1 ;18. Set Color Operator Table + .word SETPCOL-1 ;19. Set Pen Color + .word SETFCOL-1 ;20. Set Fill Color + .word SETXMOD-1 ;21. Set Transfer Mode + .word CHR_NOP-1 + .word CHR_NOP-1 + .word LINE_TO-1 ;24. Draw Line to X,Y + .word DOT_AT-1 ;25. Plot Point at X,Y + .word MOVE_TO-1 ;26. Move Pen to X,Y + .word CHR_NOP-1 + .word CLRVIEW-1 ;28. Clear Viewport + .word CHR_NOP-1 + .word CHR_NOP-1 + .word CHR_NOP-1 + +CHR_NOP RTS + +SETMODE LDA CHR_BUFF ;set graphics mode + STA GMODE + JMP L03C9 + +SETXMOD LDA CHR_BUFF ;set transfer mode + STA XFMODE + JMP L03C9 + +SCRNOFF LDA GMODE ;turn screen off + AND #$07 + ORA #$40 + STA SCR_MODE + JMP L03C9 + +SCRN_ON LDA GMODE ;enable graphics mode + AND #$07 + ORA #$C0 + STA SCR_MODE + JMP L03C9 + +MOV_PDN SEC ;move pen down (LF) + LDA YPOS ;subtract font height from the + SBC FHEIGHT ; current x,y position + STA YPOS + LDA YPOS+1 + SBC #$00 + STA YPOS+1 + RTS + +RET_PEN LDA VPORT_L ;return pen (CR) + STA XPOS ;set x position to the left + LDA VPORT_L+1 ; viewport edge + STA XPOS+1 + RTS + +CHARSET LDX #$04 ;character set +@1 LDA CHR_BUFF,X ;store chacter set address + STA FONT,X + DEX + BPL @1 + JMP L03C9 + +RSTVIEW LDX ZPD5 ;reset viewport + LDA #$00 + STA VPORT_L + STA VPORT_L+1 + STA VPORT_B + STA VPORT_B+1 ;left & bottom := 0 + LDA MVR_LO,X + STA VPORT_R ;viewport-right := max right value + LDA MVR_HI,X + STA VPORT_R+1 + LDA MVT_LO ;viewport-top := max top value + STA VPORT_T + LDA MVT_HI + STA VPORT_T+1 + RTS + +SETVIEW LDX #$08 ;set viewport +@1 LDA CHR_BUFF-1,X + STA VPORT_L-1,X + DEX + BNE @1 + JMP L03C9 + +RSTCOLT LDX #$7F ;reset color table +@1 LDA COLT2,X + STA COL_TAB,X + DEX + BPL @1 + JMP L03C9 + +SETCOLT LDA CHR_BUFF+4 ;set color table + AND #$0F + STA CHR_BUFF+4 + ASL A + ASL A + ASL A + ASL A + ORA CHR_BUFF+4 + STA CHR_BUFF+4 + CLV + LDX #$0F + LDA CHR_BUFF +@1 ASL A + BCC @7 + PHA + LDY #$0F + LDA CHR_BUFF+2 +@2 ASL A + BCC @5 + PHA + STY CHR_BUFF + TXA + PHA + ASL A + ASL A + ASL A + LSR CHR_BUFF + ORA CHR_BUFF + TAX + LDA COL_TAB,X + EOR CHR_BUFF+4 + BCS @3 + AND #$0F + BCC @4 +@3 AND #$F0 +@4 EOR CHR_BUFF+4 + STA COL_TAB,X + PLA + TAX + PLA +@5 DEY + BMI @6 + CPY #$07 + BNE @2 + LDA CHR_BUFF+3 + BVC @2 +@6 PLA +@7 DEX + BMI @8 + CPX #$07 + BNE @1 + LDA CHR_BUFF+1 + BVC @1 +@8 JMP L03C9 + +SETPCOL LDA CHR_BUFF ;set pen color + AND #$0F + STA PN_COL + RTS + +SETFCOL LDA CHR_BUFF ;set fill color + AND #$0F + STA F_COL + JMP L03C9 + +MOVE_TO LDX #$03 ;move to +@1 LDA CHR_BUFF,X + STA XPOS,X + DEX + BPL @1 + RTS + +DOT_AT LDX #$03 ;dot at +@1 LDA CHR_BUFF,X + STA XPOS,X + STA ZPF5,X ; ZPF5..ZPF8 + STA ZPF0,X ; ZPF0..ZPF3 + DEX + BPL @1 + JSR L0C21 ;out of bounds? + BCS @2 ;yep. Don't bother displaying it + JMP L0F9D ;Display it +@2 RTS + +LINE_TO LDX #$03 ;line to +@1 LDA XPOS,X + STA ZPF0,X ; ZPF0..ZPF3 + LDA CHR_BUFF,X + STA XPOS,X + STA ZPF5,X ; ZPF5..ZPF8 + DEX + BPL @1 + JSR L0C21 + BCS @2 + JSR L0F9D + JMP L0F02 +@2 RTS + +CLRVIEW LDX #$0A ;clear viewport +@1 LDA ZPCA,X + PHA + DEX + BPL @1 + LDA #$F0 + STA L01E6 + LDA VPORT_T + JSR CALCBASE ;calc base addr + SEC + LDA VPORT_T + SBC VPORT_B + STA ZPE8 + INC ZPE8 + LDA #$00 + STA ZPF5 + STA ZPF6 + LDA VPORT_L + LDY VPORT_L+1 + JSR CALCBYTE ;calc byte offset + STA ZPF2 + LDX ZPD5 + CPX #$03 + BEQ @2 + LDA #$0F + STA ZPD0 +@2 LDX #$04 +@3 LDA ZPCE,X + STA ZPE9,X + DEX + BPL @3 + LDA ZPD7 + ORA ZPD6 + BEQ @5 + CLC + LDA VPORT_L + SBC VPORT_R + STA ZPF3 + LDA VPORT_L+1 + SBC VPORT_R+1 + STA ZPF4 + DEC ZPF3 + BNE @4 + DEC ZPF4 +@4 JMP CL19 ; (@19) + +@5 STX ZPF3 + STX ZPF4 + LDA ZPCF + LDX ZPD5 + CPX #$03 + BNE @6 + EOR #$0F +@6 CMP #$02 + JSR CL29 ; (@29) + BEQ @9 + INC ZPF2 + AND #$03 + LSR A + BNE @7 + INC ZPF2 +@7 ROL A + JSR CL30 ; (@30) + EOR #$FF + STA ZPF3 + TXA + LDX #$15 + CMP #$03 + BNE @8 + LDX #$07 +@8 DEX + DEC ZPF3 + LDA L023A,X + CMP ZPCF + BNE @8 + LDA L0233,X + CMP ZPD0 + BNE @8 +@9 LDA VPORT_R + LDY VPORT_R+1 + JSR CALCBYTE ;calc byte offset + STA ZPF7 + LDX ZPD5 + CPX #$02 + BEQ @10 + SEC + ROR ZPD2 +@10 CPX #$03 + BCC @11 + LDA ZPD0 + CMP #$78 + JMP @12 + +@11 LDA ZPCF + CMP #$40 +@12 JSR CL29 ; (@29) + EOR #$07 + TAY + BNE @13 + INC ZPF7 + BPL @14 +@13 AND #$02 + BNE @14 + DEC ZPF7 +@14 TYA + BEQ @16 + AND #$03 + JSR CL30 ; (@30) + STA ZPF6 + TXA + LDX #$0D + CMP #$03 + BNE @15 + LDX #$FF +@15 INX + INC ZPF6 + LDA L023A,X + CMP ZPCF + BNE @15 + LDA L0233,X + CMP ZPD0 + BNE @15 +@16 SEC + LDA ZPF7 + SBC ZPF2 + BMI @17 + LSR A + STA ZPF5 + BNE CL19 ; (@19) + SEC + LDA ZPF3 + BCS @18 +@17 LDA ZPF3 + LDX ZPD5 + ADC L0254,X +@18 SBC ZPF6 + STA ZPF3 + LDA #$00 + STA ZPF6 +CL19 LDX #$04 +@20 LDA ZPF3,X + STA ZPEE,X + LDA ZPE9,X + STA ZPCE,X + DEX + BPL @20 + TAY +@21 INC ZPEE + BNE @22 + INC ZPEF + BNE @22 + JMP @23 + +@22 JSR L09B6 + JMP @21 + +@23 DEC ZPF0 + BMI @25 + LDX #$00 +@24 LDA L01B6,X + STA (ZPCA),Y + LDA L01B7,X + STA (ZPCC),Y + INY + INX + INX + CPX #$02 + BEQ @24 + BNE @23 ;always + +@25 STY ZPCE + DEC ZPF1 + BMI @26 + JSR L09B6 + JMP @25 + +@26 DEC ZPE8 + BEQ @27 + JSR L0E16 + JMP CL19 + +@27 LDX #$00 +@28 PLA + STA ZPCA,X + INX + CPX #$0B + BNE @28 + LDA #$00 + STA L01E6 + RTS + +CL29 ROL A + ROR ZPCE + ROL A + ROL ZPD2 + ROL A + AND #$07 + RTS + +CL30 TAY + CPX #$02 + BEQ @31 + LDY #$03 + BCS @31 + CMP #$02 + BCS @31 + DEY +@31 LDA L0250,Y + RTS + +L09B6 JSR L0FAA + JSR L0EA7 + RTS + +DRAWBLK LDA ZPD8 + PHA + LDA NOT_USED + STA ZPD8 + LDX #$09 +@1 LDA WIDTH_B,X + PHA + LDA CHR_BUFF+3,X + STA WIDTH_B,X + DEX + BPL @1 + LDA CHR_BUFF + STA ZPD3 + LDA CHR_BUFF+1 + STA ZPD4 + LDA CHR_BUFF+2 + STA ZPD3+$1401 + JSR PUTres ;put res onto graphics screen + LDX #$00 +@2 PLA + STA WIDTH_B,X + INX + CPX #$0A + BCC @2 + PLA + STA ZPD8 + RTS + +; ===================================================================== +; +; HARDWARE SPECIFIC CODES FOLLOWS.... +; +; ===================================================================== + +PUTres ;put character/res onto graphics screen + LDX #$03 + LDA #$F0 + STA L01E8 +@4 LDA XPOS,X + STA ZPF5,X + DEX + BPL @4 + SEC + LDA VPORT_L + SBC ZPF5 + STA ZPD9 + LDA VPORT_L+1 + SBC ZPF6 + STA ZPDA + BMI @5 + SEC + LDA L01DD+5 + SBC ZPD9 + STA L01DD+5 + LDA L01DD+6 + SBC ZPDA + STA L01DD+6 + BMI @7 + LDA VPORT_L + STA ZPF5 + LDA VPORT_L+1 + STA ZPF6 + BIT ZPD8 + BPL @5 + CLC + LDA L01DD+1 + ADC ZPD9 + STA L01DD+1 + LDA L01DD+2 + ADC ZPDA + STA L01DD+2 ;(L01DD+1):=(L01DD+1)+ZPD9 +@5 CLC + LDA ZPF5 + ADC L01DD+5 + STA ZPD9 + LDA ZPF6 + ADC L01DD+6 + STA ZPDA + SEC + LDA ZPD9 + SBC VPORT_R + STA ZPD9 + LDA ZPDA + SBC VPORT_R+1 + STA ZPDA + BMI @8 + INC L01DD+5 + BNE @6 + INC L01DD+6 +@6 SEC + LDA L01DD+5 + SBC ZPD9 + STA L01DD+5 + LDA L01DD+6 + SBC ZPDA + STA L01DD+6 + BPL @8 +@7 RTS + +@8 SEC + LDA ZPF7 + SBC VPORT_T + STA ZPD9 + LDA ZPF8 + SBC VPORT_T+1 + STA ZPDA + BMI @10 + SEC + LDA L01DD+7 + SBC ZPD9 + STA L01DD+7 + LDA L01DD+8 + SBC ZPDA + STA L01DD+8 + BMI @7 + BNE @9 + LDA L01DD+7 + BEQ @7 +@9 LDA VPORT_T + STA ZPF7 + LDA VPORT_T+1 + STA ZPF8 + CLC + LDA L01DD+3 + ADC ZPD9 + STA L01DD+3 + LDA L01DD+4 + ADC ZPDA + STA L01DD+4 +@10 SEC + LDA ZPF7 + SBC VPORT_B + STA ZPE8 + LDA ZPF8 + SBC VPORT_B+1 + STA ZPE9 + BMI @7 + SEC + LDA ZPF7 + SBC L01DD+7 + STA ZPD9 + LDA ZPF8 + SBC L01DD+8 + STA ZPDA + SEC + LDA ZPD9 + SBC VPORT_B + STA ZPD9 + LDA ZPDA + SBC VPORT_B+1 + STA ZPDA + BPL @11 + INC ZPE8 + BNE @12 +@11 SEC + LDA ZPE8 + SBC ZPD9 + STA ZPE8 + LDA ZPE9 + SBC ZPDA + STA ZPE9 +@12 LDX #$0A +@13 LDA ZPCA,X + PHA + DEX + BPL @13 + LDA ZPF7 + JSR CALCBASE ;calc base addr + LDA ZPF5 + LDY ZPF6 + JSR CALCBYTE ;calc byte offset + LDX #$04 +@14 LDA ZPCE,X + STA ZPE9,X + DEX + BPL @14 + CLC + LDA L01DD+1 + ADC L01DD+5 + STA ZPD9 + LDA L01DD+2 + ADC L01DD+6 + STA ZPDA + LDA L01DD+1 + AND #$07 + STA ZPEF + LDA ZPD9 + AND #$07 + STA ZPF1 + LDA L01DD+1 + ROR L01DD+2 + ROR A + ROR L01DD+2 + ROR A + ROR L01DD+2 + ROR A + STA ZPEE + LDA ZPD9 + ROR ZPDA + ROR A + ROR ZPDA + ROR A + ROR ZPDA + ROR A + STA ZPF0 +DB15 LDA L01DD+3 + BNE @16 + LDA L01DD+4 + BEQ @18 +@16 CLC + LDA ZPD3 + ADC WIDTH_B + STA ZPD3 + LDA ZPD4 + ADC L01DD + STA ZPD4 + BCC @17 + INC ZPD3+$1401 + INC ZPD3+$1401 +@17 LDA L01DD+3 + SEC + SBC #$01 + STA L01DD+3 + LDA L01DD+4 + SBC #$00 + STA L01DD+4 + JMP DB15 + +@18 LDX #$04 +@19 LDA ZPE9,X + STA ZPCE,X + DEX + BPL @19 + LDY ZPEE + STY ZPF2 + LDA (ZPD3),Y + LDX #$00 +@20 CPX ZPEF + BEQ @21 + ASL A + INX + BNE @20 +@21 STA ZPF4 +@22 STX ZPF3 + CPX ZPF1 + BNE @23 + LDA ZPF2 + CMP ZPF0 + BEQ @27 +@23 LDY ZPCE + BIT ZPD8 + BMI @24 + LSR ZPF4 + BPL @25 +@24 ASL ZPF4 +@25 LDA #$00 + BCS @26 + LDA #$F0 +@26 STA L01E6 + JSR L09B6 + LDX ZPF3 + INX + CPX #$08 + BNE @22 + LDX #$00 + INC ZPF2 + LDY ZPF2 + LDA (ZPD3),Y + STA ZPF4 + JMP @22 + +@27 DEC ZPE8 + BEQ @29 + JSR L0E16 + CLC + LDA ZPD3 + ADC WIDTH_B + STA ZPD3 + LDA ZPD4 + ADC L01DD + STA ZPD4 + BCC @28 + INC ZPD3+$1401 + INC ZPD3+$1401 +@28 JMP @18 + +@29 LDX #$00 +@30 PLA + STA ZPCA,X + INX + CPX #$0B + BNE @30 + LDA #$00 + STA L01E6 + STA L01E8 + RTS + +; See "Principles of Interactive Computer Graphics", second edition +; Newman & Sproull, pages 65-68 + +L0C21 LDY #$0F + JSR L0D00 ;check bounds + STA ZPF4 + LDY #$14 + JSR L0D00 ;check bounds + STA ZPF9 +@1 LDA ZPF9 + ORA ZPF4 + AND #$0F + BNE @2 + CLC ;both endpoints are within the viewport + RTS + +@2 LDA ZPF4 + AND ZPF9 + AND #$0F + BEQ @4 + SEC ;both endpoints are outside viewport and the +@3 RTS ; line does not enter viewport + +@4 LDA ZPF4 ;both endpoints outside, but check if the + AND #$0F ; line crosses into the viewport + BEQ @5 + LDX #$00 + LDY #$0F + JSR L0D59 ;copy + LDX #$05 + LDY #$14 + JSR L0D59 ;copy + JSR @6 ;midpoint subdivision + BCS @3 + LDX #$0F + LDY #$0A + JSR L0D59 ;copy + BEQ @1 +@5 LDA ZPF9 + AND #$0F + BEQ @1 + LDX #$00 + LDY #$14 + JSR L0D59 ;copy + LDX #$05 + LDY #$0F + JSR L0D59 + JSR @6 + BCS @3 + LDX #$14 + LDY #$0A + JMP L0D59 + +; ---- Mid-Point Subdivision ---- +@6 LDA ZPE5 ;border bits (from) + EOR ZPEA ; (to) + AND ZPE5 + ASL A + ASL A + ASL A + ASL A ;mul 16 (move lo nybble to hi) + STA ZPDF + AND ZPEA + BEQ @8 ;br to try it out + LDA ZPEA + AND #$0F + BNE @7 ;br if it's completely outside + LDX #$0A + LDY #$05 + CLC + JMP L0D59 + +@7 SEC ;completely outside viewport + RTS + +@8 STA ZPDB + STA ZPDD + +@9 ROL ZPDB + LDA ZPE1 ;XPOS (from) + ADC ZPE6 ;XPOS (to) + STA ZPEB + LDA ZPE2 ;XPOS+1 (from) + ADC ZPE7 ;XPOS+1 (to) + BVS @10 + CMP #$80 +@10 ROR A ;div 2 + STA ZPEC + ROR ZPEB ;div 2 + ROR ZPDB + ROL ZPDD + LDA ZPE3 ;YPOS (from) + ADC ZPE8 ;YPOS (to) + STA ZPED + LDA ZPE4 ;YPOS+1 (from) + ADC ZPE9 ;YPOS+1 (to) + BVS @11 + CMP #$80 +@11 ROR A ;div 2 + STA ZPEE + ROR ZPED ;div 2 + ROR ZPDD + LDY #$0A + JSR L0D00 ;check if the midpoint is inside vport + STA ZPEF + AND ZPE5 + AND #$0F + BEQ @13 ;br if inside viewport + LDX #$00 + JSR L0D59 + LDA ZPE5 + AND ZPEA + AND #$0F + BEQ @9 +@12 CLC ;completely inside viewport + RTS + +@13 LDA ZPEF + AND ZPDF + BNE @12 ;all done + LDX #$05 + JSR L0D59 + BEQ @9 ;go around for another try + +; CHECK VIEWPORT BOUNDS inside outside +; bit # 7 6 5 4 3 2 1 0 +; leaves flag in acc -> T B R L T B R L + +L0D00 LDA #$00 ;check viewport bounds + LDX ZPE2,Y ;XPOS+1 + BMI @6 ; br if neg -- outside viewport + CPX VPORT_L+1 + BCC @6 ; br if VPORT_L+1>XPOS+1 + BNE @2 ; br if not equal + LDX ZPE1,Y ;XPOS + CPX VPORT_L + BCC @6 ; br if VPORT_L>XPOS + BEQ @5 ; br if equal +@1 LDX ZPE2,Y ;XPOS+1 +@2 CPX VPORT_R+1 + BCC @7 ; br if VPORT_R+1>XPOS+1 + BNE @3 ; br if not equal + LDX ZPE1,Y ;XPOS + CPX VPORT_R + BCC @7 ; br if VPORT_R>XPOS + BEQ @4 ; br if equal +@3 ORA #BITON1 ;outside of the right edge + BNE @7 ; always +@4 ORA #BITON5 ;inside of the right edge + BNE @7 ; always +@5 ORA #BITON4 ;inside of the left edge + BNE @1 ; always -- go check right edge +@6 ORA #BITON0 ;outside of the left edge +@7 LDX ZPE4,Y ;YPOS+1 + BMI @12 ; br if neg -- outside + BNE @9 ; br if hi-byte is not zero -- outside + LDX ZPE3,Y ;YPOS + CPX VPORT_B + BCC @12 + BEQ @11 +@8 CPX VPORT_T + BEQ @10 ; br if equal + BCC @13 ; br if VPORT_T>YPOS +@9 ORA #BITON3 ;above top edge (outside) + RTS + +@10 ORA #BITON7 ;at top edge (inside) + RTS + +@11 ORA #BITON6 ;at bottom edge (inside) + BNE @8 ; br always -- go check top edge +@12 ORA #BITON2 ;below bottom edge (outside) +@13 RTS + +L0D59 LDA #$05 + STA ZPE0 +@1 LDA ZPE1,Y + STA ZPE1,X + INX + INY + DEC ZPE0 + BNE @1 + RTS + +CALCBASE ;Calculate base address -- ACC:=YPOS + STA ZPD9 + SEC + LDA #$BF + SBC ZPD9 + TAY + LSR A + LSR A + LSR A ;div 8 + TAX + TYA + ASL A + ASL A ;mul 4 + AND #$1C + ORA L01F3,X + TAY + ORA L01B2 + STA ZPCB + TYA + ORA L01B3 + STA ZPCD + LDA L020B,X + STA ZPCA + STA ZPCC + STX ZPE7 + RTS + +CALCBYTE ;Calculate byte offset -- ACC:=XPOS, Y_REG:=XPOS+1 + SEC + BEQ @3 ; br if XPOS+1=00 + DEY + BEQ @1 + LDY #$48 ;gets here when X_HI=2 + ADC #$01 + BCC @2 ; br if XPOS<=255 +@1 LDY #$23 ;gets here when X_HI=1 + ADC #$04 + BCC @2 + INY + SBC #$07 +@2 INY +@3 SBC #$07 ; DIV 7 -- the old-fashioned way + BCS @2 + TAX ; remainder into X + TYA + LDY COL_TAB+$35,X + STY ZPCF + LDY ZPD5 + CPY #$02 + STY ZPD2 + BCC @4 + BEQ @5 + ASL A + LDY COL_TAB+$20,X + STY ZPD0 + LDY COL_TAB+$27,X + STY ZPCF + STX ZPD1 ;remainder (in 2's complement form) + CPX #$FC + ADC #$00 +@4 STA ZPCE ;byte offset + RTS ; something get left in ACC + +@5 LSR A + STA ZPCE ;byte offset + ROR ZPD2 + RTS + +L0DD8 BPL L0E16 + CLC + LDA ZPCB + BIT L025A + BNE L0E08 + ASL ZPCA + BCS L0E00 + BIT L0258 + BEQ L0DF0 + ADC #$1F + SEC + BCS L0E02 +L0DF0 ADC #$23 + PHA + LDA ZPCA + ADC #$B0 + BCS L0DFB + ADC #$F0 +L0DFB STA ZPCA + PLA + BCS L0E02 +L0E00 ADC #$1F +L0E02 ROR ZPCA + LDX ZPCA + STX ZPCC +L0E08 ADC #$FC +L0E0A STA ZPCB + AND #$1F + STA ZPE7 + ORA L01B3 + STA ZPCD + RTS + +L0E16 CLC + LDA ZPCB + ADC #$04 + BIT L025A + BNE L0E0A + ASL ZPCA + BCC L0E3E + ADC #$E0 + CLC + BIT L0259 + BEQ L0E40 + LDA ZPCA + ADC #$50 + EOR #$F0 + BEQ L0E36 + EOR #$F0 +L0E36 STA ZPCA + LDA ZPCB + AND #$E0 + BCC L0E40 +L0E3E ADC #$E0 +L0E40 ROR ZPCA + LDX ZPCA + STX ZPCC + BCC L0E0A +L0E48 BVS L0E4D + JMP L0EA7 + +L0E4D LDX ZPD5 + CPX #$02 + BEQ L0E6B + BCS L0E84 + LSR ZPCF + BCC L0E6A + DEY + BPL L0E64 +L0E5C ROL ZPCF + INY + STY ZPCE + RTS + +L0E62 LDY #$27 +L0E64 LDA #$40 + STA ZPCF + STY ZPCE +L0E6A RTS + +L0E6B LSR ZPCF + BCC L0E6A + LDA #$40 + STA ZPCF + ASL A + EOR ZPD2 + STA ZPD2 + BPL L0E6A + DEY + STY ZPCE + BPL L0E6A + LSR ZPD2 + SEC + BCS L0E5C +L0E84 LDX ZPD1 + CPX #$FC + BNE L0E8B + DEY +L0E8B DEX + CPX #$F9 + BCS L0E98 + LDX #$FF + DEY + BPL L0E98 + INY + LDX #$F9 +L0E98 STY ZPCE + STX ZPD1 + LDA COL_TAB+$27,X + STA ZPCF + LDA COL_TAB+$20,X + STA ZPD0 + RTS + +L0EA7 LDX ZPD5 + CPX #$02 + BEQ @3 + BCS @4 + ASL ZPCF + BPL @2 + INY + CPY #$28 + BCC @1 + JMP L0E62 + +@1 LDA #$01 + STA ZPCF + STY ZPCE +@2 RTS + +@3 ASL ZPCF + BPL @2 + LDA #$01 + STA ZPCF + LDA #$FF + EOR ZPD2 + STA ZPD2 + BMI @2 + INY + STY ZPCE + CPY #$28 + BCC @2 + ROR ZPD2 + JMP L0E62 + +@4 LDX ZPD1 + CPX #$FB + BNE @5 + INY +@5 INX + BNE @6 + LDX #$F9 + INY + CPY #$28 + BCC @6 + LDX #$FF + LDY #$27 +@6 STY ZPCE + STX ZPD1 + LDA COL_TAB+$20,X + STA ZPD0 + LDA COL_TAB+$27,X + STA ZPCF + RTS + +L0F02 SEC + LDA ZPF5 + SBC ZPF0 + PHA + LDA ZPF6 + SBC ZPF1 + STA ZPD9 + BCS @1 + PLA + EOR #$FF + ADC #$01 + PHA + LDA #$00 + SBC ZPD9 +@1 STA ZPDE + PLA + STA ZPDD + SEC + LDA ZPF7 + SBC ZPF2 + BCS @2 + EOR #$FF + ADC #$01 +@2 STA ZPDB + ROR ZPD9 + LDY ZPCE + LDX ZPDE + BNE @3 + CMP ZPDD + BCS @7 +@3 STX ZPE2 + TXA + LSR A + STA ZPE4 + LDA ZPDD + BNE @4 + DEC ZPE2 +@4 STA ZPE1 + ROR A + STA ZPE3 +@5 LDA ZPE3 + SEC + SBC ZPDB + STA ZPE3 + BCS @6 + DEC ZPE4 + BPL @6 + ADC ZPDD + STA ZPE3 + LDA ZPE4 + ADC ZPDE + STA ZPE4 + LDA ZPD9 + JSR L0DD8 +@6 BIT ZPD9 + JSR L0E48 + JSR L0FAA + DEC ZPE1 + BNE @5 + DEC ZPE2 + BPL @5 + RTS + +@7 STA ZPE1 + TAX + BEQ @10 + LSR A + STA ZPE4 +@8 LDA ZPE4 + SEC + SBC ZPDD + STA ZPE4 + BCS @9 + ADC ZPDB + STA ZPE4 + BIT ZPD9 + JSR L0E48 +@9 LDA ZPD9 + JSR L0DD8 + JSR L0FAA + DEC ZPE1 + BNE @8 +@10 RTS + +L0F9D LDA ZPF2 ;JSR, JMP from LINETO + JSR CALCBASE ;calc base addr + LDA ZPF0 + LDY ZPF1 + JSR CALCBYTE ;calc byte offset + TAY + +L0FAA BIT ZPD7 + LDX ZPD5 + DEX + BEQ @5 + LDA L01E6 + ASL A + LDA PN_COL + BCC @1 + LDA F_COL +@1 CPX #$02 + BNE @2 + JMP L1054 + +@2 BVC @3 + JSR L1199 +@3 CMP #$00 + BEQ @4 + LDA ZPCF +@4 JMP L1081 + +@5 BIT ZPE7 + BPL @6 + CPY ZPE5 + BEQ @8 +@6 LDA F_COL + STA ZPDF + LDA PN_COL + STA ZPE0 + BIT ZPD7 + BVC @7 + LDA L01E6 + PHA + LDA #$F0 + STA L01E6 + SEC + JSR L11AB + STA ZPDF + LDA #$00 + STA L01E6 + CLC + JSR L11AB + STA ZPE0 + PLA + STA L01E6 +@7 LDA ZPE0 + ASL A + ASL A + ASL A + ASL A + ORA ZPDF + STA L01E6+1 +@8 LDX ZPCF + LDA L01E6 + ASL A + LDA #$F0 + BCC @9 + LDA #$0F +@9 STA ZPCF + AND L01E6+1 + JSR L10A8 + BIT L01E8 + BPL @11 + LDA L01E6 + ASL A + LDA #$0F + BCC @10 + LDA #$F0 +@10 STA ZPCF + LDA ZPCF + AND L01E6+1 + JSR L10A8 +@11 STX ZPCF + LDA (ZPCA),Y + ORA ZPCF + LDX L01E6 + BEQ @12 + EOR ZPCF +@12 STA (ZPCA),Y + LDA #$F0 + STA ZPE7 + STY ZPE5 + RTS + +L1054 BVC @1 + JSR L11B7 +@1 JSR L1148 + TAX + LDA ZPCF + BEQ @2 + LDA ZPDF + JSR L1085 +@2 LDA ZPCF + PHA + LDA ZPD0 + BEQ @4 + STA ZPCF + CMP #$60 + PHP + BNE @3 + DEY +@3 TXA + JSR L10A8 + PLP + BNE @4 + INY +@4 PLA + STA ZPCF + RTS + +L1081 BIT ZPD2 + BMI L10A8 + +L1085 BIT ZPD7 + BPL @1 + EOR ZPCF +@1 BIT ZPD6 + BMI @5 + BVS @4 + EOR (ZPCA),Y + AND ZPCF +@2 EOR (ZPCA),Y +@3 STA (ZPCA),Y + RTS + +@4 ORA (ZPCA),Y + BVS @3 +@5 BVC @2 + EOR #$FF + EOR ZPCF + AND (ZPCA),Y + BVS @3 + +L10A8 BIT ZPD7 + BPL @1 + EOR ZPCF +@1 BIT ZPD6 + BMI @5 + BVS @4 + EOR (ZPCC),Y + AND ZPCF +@2 EOR (ZPCC),Y +@3 STA (ZPCC),Y + RTS + +@4 ORA (ZPCC),Y + BVS @3 +@5 BVC @2 + EOR #$FF + EOR ZPCF + AND (ZPCC),Y + BVS @3 + +L10CB LDY ZPCE ;read color at pen position + LDX ZPD5 + CPX #$03 + BEQ L10F6 + LDA ZPCF + BIT ZPD2 + BMI @1 + AND (ZPCA),Y + BCC @2 +@1 AND (ZPCC),Y +@2 BEQ @3 + LDA #$0F +@3 CPX #$01 + BEQ @4 + RTS + +@4 TAX + LDA (ZPCC),Y + CPX #$00 + BEQ @5 + LSR A + LSR A + LSR A + LSR A +@5 AND #$0F + RTS + +L10F6 LDA (ZPCA),Y + AND ZPCF + STA ZPDF + LDA ZPD0 + CMP #$60 + PHP + BNE @1 + DEY +@1 AND (ZPCC),Y + PLP + BNE @2 + INY +@2 LDX ZPD1 + INX + BNE @3 + LSR A + LSR A + LSR A + RTS + +@3 INX + BNE @4 + ROL ZPDF + ROL ZPDF + ROL A + RTS + +@4 INX + BNE @5 + LDA ZPDF + LSR A + LSR A + RTS + +@5 INX + BNE @6 + ROL A + ROL A + ROL ZPDF + ROL A + ROL ZPDF + LDA ZPDF + RTS + +@6 INX + BNE @7 + LSR A + RTS + +@7 INX + BNE @8 + ASL ZPDF + ASL ZPDF + ROL A + ASL ZPDF + ROL A + ASL ZPDF + ROL A + RTS + +@8 LDA ZPDF + RTS + +L1148 LDX ZPD1 + INX + BNE @1 + STX ZPDF + ASL A + ASL A + ASL A + RTS + +@1 INX + BNE @2 + LSR A + TAX + LDA #$00 + ROR A + ROR A + STA ZPDF + TXA + RTS + +@2 INX + BNE @3 + ASL A + ASL A + STA ZPDF + TXA + RTS + +@3 INX + BNE @4 + STX ZPDF + LSR A + ROR ZPDF + LSR A + ROR ZPDF + LSR ZPDF + TAX + LDA ZPDF + STX ZPDF + RTS + +@4 INX + BNE @5 + ASL A + STX ZPDF + RTS + +@5 INX + BNE @6 + STX ZPDF + LSR A + ROR ZPDF + LSR A + ROR ZPDF + LSR A + ROR ZPDF + LSR ZPDF + RTS + +@6 STA ZPDF + LDA #$00 + RTS + +L1199 LDA ZPCF + BIT ZPD2 + BMI @1 + AND (ZPCA),Y + BPL @2 +@1 AND (ZPCC),Y +@2 BEQ L11BA + LDA #$0F + BNE L11BA +L11AB LDA (ZPCC),Y + BCS @1 + LSR A + LSR A + LSR A + LSR A +@1 AND #$0F + BPL L11BA +L11B7 JSR L10F6 +L11BA STA ZPDC + LDA L01E6 + BPL @1 + LDA F_COL + JMP @2 + +@1 LDA PN_COL +@2 ASL A + ASL A + ASL A + LSR ZPDC + ORA ZPDC + TAX + LDA COL_TAB,X + BCS @3 + LSR A + LSR A + LSR A + LSR A +@3 AND #$0F + RTS + + .endproc