; File: CC.PROM.DS ; Date: 15-Nov-83 ; ; DISPLAY DRIVER FOR PROM (mb) 05/18/82 ; ; BOTH horizontal and vertical display driver ; contains default window records, copies them into memory ; contains default character sets ; no CRTST code: no window functions DSClf equ $0A ;line feed character DSCcr equ $0D ;carriage return character DSCesc equ $1B ;escape character DSCblnk equ $20 ;blank character DSClca equ $61 ;lower case "a" DSClcz equ $7A ;lower case "z" DSCdiff equ $20 ; ; Character Set Record Equates ; ;Stblloc equ 0 ;character set data pointer (not used) CSlpch equ 4 ;scanlines per character CSbpch equ 6 ;bits per character CSfrstch equ 8 ;first character code - ascii CSlastch equ 10 ;last character code - ascii CSmask equ 12 ;mask used in positioning cells CSattr1 equ 16 ;attributes ; bit 0 = 1 - vertical orientation CSattr2 equ 17 ;currently unused CSdata equ 18 ;offset of char data from char record ; ; Window Record Equates ; WRcharpt equ 0 ;character set pointer WRhomept equ 4 ;home (upper left) pointer WRcuradr equ 8 ;current location pointer WRhomeof equ 12 ;bit offset of home location WRbasex equ 14 ;home x value, relative to root window WRbasey equ 16 ;home y value, relative to root window WRlngthx equ 18 ;maximum x value, relative to window (bits) WRlngthy equ 20 ;maximum y value, relative to window (bits) WRcursx equ 22 ;current x value (bits) WRcursy equ 24 ;current y value (bits) WRbitofs equ 26 ;bit offset of current address WRgrorgx equ 28 ;graphics - origin x (bits relative to home loc) WRgrorgy equ 30 ;graphics - origin y (bits relative to home loc) WRattr1 equ 32 ;attributes WRattr2 equ 33 ;attributes vert equ 0 ; 1 = vertical, 0 = horizontal WRstate equ 34 ;used for decoding escape sequences WRrcdlen equ 35 ;window description record length ; WRlength equ 36 ;actual window record length page ; ; DSinit - Initialize display driver ; DSinit MOVEM.L D4/A0-A2,-(SP) ;save registers MOVE.W #DSdefOf,CPscnofs.W ;set bytes per scan line LEA DSwndH,A0 ;assume horizontal orientation LEA DScsetH,A2 ;* BTST #3,IObootsw.L ;is display horizontal? BOFF.S DSinit1 ;yes, go on LEA DSwndV,A0 ;set vertical orientation LEA DScsetV,A2 ;* DSinit1 LEA CPwndrcd.W,A1 ;get pointer to RAM window record 0.8 MOVEQ #WRlength-1,D4 ;get window record length 0.6 DSinit2 MOVE.B (A0)+,(A1)+ ;copy window record to RAM 0.6 DBRA D4,DSinit2 ;* LEA CPwndrcd.W,A0 ;get RAM window record pointer 0.8 MOVE.L A2,WRcharpt(A0) ;set character set record pointer BSR DScurs ;display cursor on screen MOVEM.L (SP)+,D4/A0-A2 ;restore registers RTS ;return ; ; DScvtUC - Convert character to upper case ; ; Enter: D0.B = ASCII character ; ; Exit: D0.B = upper case ASCII character ; DScvtUC CMPI.B #DSClca,D0 ;is character lower case? BLO.S DScvtU1 ;no, return CMPI.B #DSClcz,D0 ;* BHI.S DScvtU1 ;no, return SUBI.B #DSCdiff,D0 ;convert character to upper case DScvtU1 RTS ;return ; ; DSputst - Display a string ; ; Enter: A0.L - Character string pointer ; (terminated by 0) ; DSputst movem.l D0/A0,-(SP) ;save registers ; DSpst1 move.b (a0)+,d0 ;get next character beq.s DSpst9 ;finished, return bsr.s DSputch ;output character bra.s DSpst1 ;get next character ; DSpst9 movem.l (SP)+,D0/A0 ;restore registers rts ;return page ; ; DSputch - Display a character ; ; Enter: D0.B - Character to output ; DSputch MOVEM.L D0-D7/A0-A6,-(SP) ;save registers andi.w #$7F,d0 ;make character 7 bits LEA CPwndrcd.W,A0 ;get RAM window record pointer 0.8 tst.b CPextcrt.w ;using external CRT? 0.8 bon.s DSxCrt ;yes, use data comm 0 0.8 bsr SBprom2 ;debug PROM boot? 0.7 beq.s DSxCrt ;yes, use data comm 0 0.7 MOVE.L WRcharpt(A0),A2 ;get character set record pointer CLR.L D3 ; MOVE.B WRstate(A0),D3 ; LSL.W #1,D3 ;convert to state table index LEA DSsTbl,A1 ; MOVE.W 0(A1,D3.W),D3 ;D3 = dist from DSsTbl JMP 0(A1,D3.W) ;go to current state processing ; DSnxtSt ADDQ.B #1,WRstate(A0) ;increment for next state BRA.S DSexit ;return ; DSxCrt move.l #DScPort,a1 ;get UART pointer 0.7 DSxCrt1 btst #DSwrBit,DSuSt(a1) ;is UART output busy? 0.7 boff.s DSxCrt1 ;yes, try again 0.7 move.b d0,DSuDa(a1) ;output the character 0.7 cmpi.b #DSCcr,d0 ;was it a ? 0.7 bne.s DSreset ;no, go on 0.7 btst #1,CPdspflg.w ;auto line feed? 0.7 bon.s DSreset ;yes, bypass insertion 0.7 moveq #DSClf,d0 ;add a 0.7 BRA.S DSxCrt1 ;output LF 0.8 DSreset CLR.B WRstate(A0) ;reset current state ; DSexit MOVEM.L (SP)+,D0-D7/A0-A6 ;restore registers RTS ;return page DSst0 CMP.B #DSCesc,D0 ;is char ESC? BEQ.S DSnxtSt ;yes, go to next state CMP.W CSfrstch(A2),D0 ;ascinum < first char? BLO.S DSctl ;yes, it's a control char BSR.S DSshwCh ;display character BSR DSincx ;inccurx BRA.S DSexit ;return DSctl SUBQ.W #8,D0 ;commence decoding ctrl char BMI.S DSexit ; CMPI.W #5,D0 ;ascinum in [8..13]? BHI.S DSexit ;yes, do cursor ctrl LEA DScTbl,A3 ;A3==>jump table for ctrl chars LSL.W #1,D0 ;make it word count PEA DSexit ;ensure RTS to exit ;---- MOVE.W 0(A3,D0),D0 ;D0 is offset from DScTbl 0.8 ;---- JMP 0(A3,D0) ;jump to proper routine 0.8 BRA.S DSgortn ;goto proper routine 0.8 DSesc CLR.W D1 ;initialize index reg LEA DSeTbl,A3 ;A3==> beginning of table ; DSesc1 CMP.W 0(A3,D1),D0 ;does table entry match char? BEQ.S DSesc2 ;yes, go on ADDQ.W #4,D1 ;go to next entry TST.W 0(A3,D1) ;end of table? BPL.S DSesc1 ;no, loop BRA.S DSreset ;return ; DSesc2 MOVE.W D1,D0 ;set D0 to table offset ADDQ.W #2,D0 ; PEA DSreset ;ensure RTS to reset state DSgortn MOVE.W 0(A3,D0),D0 ;D0 is offset from DSeTbl JMP 0(A3,D0) ;jump to proper routine page ; ; DSshwCh - Display character ; ; Enter: A0.L = window record pointer ; A2.L = character set record pointer ; D0.W = ASCII character ; ; Note: Character set must be in bytes, not words ; DSshwCh BSR DScvtUC ;convert character to upper case CMP.W CSfrstch(A2),D0 ;is character in character set? BLT.S DSshow1 ;no, output space CMP.W CSlastch(A2),D0 ;* BLE.S DSshow2 ;yes, output character DSshow1 MOVE.W #DSCblnk,D0 ;no, output space ; DSshow2 SUB.W CSfrstch(A2),D0 ;get relative character position LEA DScsetV+CSdata,a3 ;get pointer to character data MULU #DScellW,D0 ;* ADDA.L D0,A3 ;* MOVE.L WRcuradr(A0),A4 ;get current character address MOVE.W CSlpch(A2),D1 ;get number of scan lines for character SUBQ.W #1,D1 ;get count for DBRA MOVE.W CPscnofs.W,D3 ;get scan line length MOVE.W WRbitofs(A0),D5 ;get bit offset of character in cell MOVE.L CSmask(A2),D6 ;get character mask BTST #vert,WRattr2(A0) ;is this vertical orientation? BOFF.S DSshow6 ;no, output horizontal character ; ; output vertical orientation character ; MOVE.L D6,D0 ; NOT.L D0 ;D0 = inverted mask ROR.L D5,D6 ;D6 = positioned mask DSshow3 MOVE.B (A3)+,D2 ;D2 = char data LSL.W #8,D2 ; SWAP D2 ;get char in high word AND.L D0,D2 ;clear rest of source char LSR.L D5,D2 ;position source char AND.L D6,(A4) ;clear dest char area OR.L D2,(A4) ;move in character SUBA.W D3,A4 ; DBRA D1,DSshow3 ;repeat for D1:=CSlpch-1 to 0 BRA.S DSshow9 ;return page ; ; output horizontal orientation character ; DSshow6 TST.W -(A4) ;A4==>long word with cell ROL.L D5,D6 ;D6 = positioned mask MOVE.L D6,D4 ; NOT.L D4 ;D4 = inverted mask moveq #7,d0 ;use 8 bits of character data ; DSshow7 clr.l d2 ;clear current scan line of character tst.w d0 ;have we used 8 bits of character data? blt.s DSshw76 ;yes, pad with space btst d0,0(a3) ;construct next horizontal character boff.s DSshw71 ;* from vertical character data bset #0,d2 ;* DSshw71 btst d0,1(a3) ;* boff.s DSshw72 ;* bset #1,d2 ;* DSshw72 btst d0,2(a3) ;* boff.s DSshw73 ;* bset #2,d2 ;* DSshw73 btst d0,3(a3) ;* boff.s DSshw74 ;* bset #3,d2 ;* DSshw74 btst d0,4(a3) ;* boff.s DSshw75 ;* bset #4,d2 ;* DSshw75 btst d0,5(a3) ;* boff.s DSshw76 ;* bset #5,d2 ;* DSshw76 subq #1,d0 ;indicate another bit used LSL.L D5,D2 ;shift char into position AND.L D6,(A4) ; OR.L D2,(A4) ; SUBA.W D3,A4 ; DBRA D1,DSshow7 ; DSshow9 RTS ;return page ; ; DScrsR -- cursor right ; DScrsR BSR DScurs0 ;remove cursor DSincx MOVE.W WRcursx(A0),D1 ;get current cursor X position ADDQ.W #DScellW,D1 ;increment 1 character space 0.6 MOVE.W D1,WRcursx(A0) ;save new cursor X position 0.6 CMP.W WRlngthx(A0),D1 ;at end of line? 0.6 BGE.S DSrtrn1 ;yes, do carriage return 0.6 BRA.S DScurs ;show cursor 0.6 ; ; DScrsU -- cursor up ; DScrsU BSR.S DScurs0 ;remove cursor BRA.S DSdecy ;decrement cursor Y position ; ; DSrtrn -- return ; DSrtrn BSR.S DScurs0 ;remove cursor DSrtrn1 CLR.W WRcursx(A0) ;zero current cursor X position BTST #1,CPdspflg.w ;auto line feed? BOFF.S DSincy ;no, increment cursor Y position BRA.S DScurs ;show cursor ; ; DScrsD -- cursor down ; DScrsD BSR.S DScurs0 ;remove cursor DSincy MOVE.W WRcursy(A0),D1 ;get current cursor Y position ADDI.W #DScellY,D1 ;increment 1 character space 0.6 MOVE.W D1,WRcursy(A0) ;save new cursor Y position 0.6 CMP.W WRlngthy(A0),D1 ;at bottom of screen? 0.6 BLE.S DScurs ;on bottom line? 0.6 BRA DSclAL ;yes, wrap to home position 0.6 ; ; DScrsL -- cursor left ; DScrsL BSR.S DScurs0 ;remove cursor DSdecx TST.W WRcursx(A0) ;at beginning of line? BEQ.S DSwrapx ;yes, wrap to previous line SUBQ.W #DScellW,WRcursx(A0) ;decrement 1 character space BRA.S DScurs ;show cursor page ; ; DScrsH -- cursor home ; DScrsH BSR.S DScurs0 ;remove cursor DScrsH1 CLR.W WRcursx(A0) ;zero current cursor X position CLR.W WRcursy(A0) ;zero current cursor Y position BRA.S DScurs ;show cursor DSwrapx BSR.S DSwrap ; MOVE.W D0,WRcursx(A0) ; DSdecy TST.W WRcursy(A0) ;at top line? BEQ.S DScurs ;yes, show cursor SUBI.W #DScellY,WRcursy(A0) ;decrement 1 character space BRA.S DScurs ;show cursor DSwrap CLR.L D0 ;get current cursor X position MOVE.W WRlngthx(A0),D0 ;* MOVEQ #DScellW,D2 ;get character width DIVU D2,D0 ; MULU D2,D0 ; RTS ;return DScurs BSR.S DScrsAd ;compute cursor address DScurs0 MOVE.W CSlpch(A2),D1 ;get scan lines per character SUBQ.W #1,D1 ;set loop counter MOVE.L WRcuradr(A0),A4 ;get current cursor address MOVE.W WRbitofs(A0),D5 ;get current cursor bit offset MOVE.L CSmask(A2),D7 ;get character mask BTST #vert,WRattr2(A0) ;vertical orientation? BOFF.S DScurs1 ;no ROR.L D5,D7 ; BRA.S DScurs2 ; DScurs1 TST.W -(A4) ; ROL.L D5,D7 ; DScurs2 NOT.L D7 ;D7 = positioned inverted mask DScurs3 EOR.L D7,(A4) ;invert character SUBA.W CPscnofs.W,A4 ;* DBRA D1,DScurs3 ;* RTS ;return DScrsAd MOVEM.W WRcursx(A0),D5-D6 ;get current cursor position BSR DSaddr ;compute cursor address MOVE.W D7,WRbitofs(A0) ;save cursor bit offset MOVE.L A4,WRcuradr(A0) ;save cursor address RTS ;return page ; ; DSclAL -- clear screen ; DSclAL BSR DScrsH1 ;home cursor ; ; DSclES -- clear to end of screen ; DSclES BSR.S DSclEL ;first clear this line BTST #vert,WRattr2(A0) ;vertical orientation? BON.S DSclES2 ;yes, clear vertical screen ; --- clear to end of horizontal screen MOVE.W WRcursy(A0),D6 ;get current cursor Y position DSclES1 ADDI.W #DScellY,D6 ;increment to next line MOVE.W WRlngthy(A0),D0 ;get bottom of screen limit CMP.W D0,D6 ;at bottom of screen? BGE.S DSclES9 ;yes, return SUB.W D6,D0 ;compute number of scan lines to clear CLR.W D3 ;set starting X position to 0 BSR.S DSclrH ;clear to bottom of screen BRA.S DSclES9 ;return ; --- clear to end of vertical screen DSclES2 MOVE.W WRcursy(A0),D0 ;get current cursor Y position DSclES3 ADDI.W #DScellY,D0 ;increment to next line CMP.W WRlngthy(A0),D0 ;at bottom of screen? BGE.S DSclES9 ;yes, return MOVE.W D0,D6 ; CLR.W D5 ; BSR.S DSclrV ;clear one vertical line BRA.S DSclES3 ;repeat until all lines cleared ; DSclES9 RTS ;return ; ; DSclEL -- clear to end of line ; DSclEL BSR DScurs0 ;remove cursor MOVEM.W WRcursx(A0),D5-D6 ;get current cursor X and Y BTST #vert,WRattr2(A0) ;vertical orientation BOFF.S DSclEL1 ;no, clear horizontal line BSR.S DSclrV ;clear one vertical line BRA.S DSclEL2 ;show cursor ; DSclEL1 MOVEQ #DScellY-1,D0 ;D0 = #scanlines to clear MOVE.W D5,D3 ; BSR.S DSclrH ;clear one horizontal line DSclEL2 BRA DScurs0 ;show cursor page DSclrV MOVE.W WRlngthx(A0),D4 ;get length of line SUB.W D5,D4 ;compute number of scan lines clear BSR DSaddr ;compute cursor address MOVE.W CPscnofs.W,D1 ;get bytes per scan line MOVE.L CSmask(A2),D6 ;get character mask ROR.L D7,D6 ;align character mask DSclrV1 AND.L D6,(A4) ;clear one scan line SUBA.W D1,A4 ;compute address of next scan line DBRA D4,DSclrV1 ;repeat to end of line RTS ;return DSclrH MOVE.W WRlngthx(A0),D4 ;D5 = x, D6 = y ADDQ.W #1,D4 ; MOVE.W D4,D5 ; SUB.W D3,D4 ; BSR DSaddr ;A4 = addr(x,y), D7 = bitnum SUB.W D7,D4 ; TST.W D7 ; BNE.S DSclrH1 ; TST.W (A4)+ ; DSclrH1 MOVE.W D4,D3 ; ANDI.W #$F,D3 ; ASR.W #4,D4 ; SUBQ.W #1,D4 ; MOVEQ #-1,D1 ; MOVE.W D1,D2 ; LSL.W D7,D1 ; LSR.W D3,D2 ; DSclrH2 MOVE.L A4,A5 ; TST.W D7 ; BEQ.S DSclrH3 ; AND.W D1,(A5)+ ; DSclrH3 MOVE.W D4,D6 ; BMI.S DSclrH5 ; DSclrH4 CLR.W (A5)+ ; DBRA D6,DSclrH4 ; DSclrH5 TST.W D3 ; BEQ.S DSclrH6 ; AND.W D2,(A5) ; DSclrH6 SUBA.W CPscnofs.W,A4 ; DBRA D0,DSclrH2 ; RTS ;return page DStab MOVE.W WRcursx(A0),D0 ;get current cursor X position AND.L #$FFFF,D0 ;clear hi word MOVEQ #DScellW*8,D2 ; DIVU D2,D0 ;find next tab to right ADDQ.W #1,D0 ; MULU D2,D0 ; CMP.W WRlngthx(A0),D0 ;new x > right? BLS.S DStab1 ;no, change x RTS ;return DStab1 BSR DScurs0 ;remove cursor MOVE.W D0,WRcursx(A0) ;save new cursor X position BRA DScurs ;show cursor ; ; DSaddr -- compute cursor address ; ; Enter: D5 = x ; D6 = y ; ; Exit: DSaddr (x,y) in A4, bit offset in D7 ; DSaddr MOVEA.L WRhomept(A0),A4 ;get home pointer for orientation BTST #vert,WRattr2(A0) ;vertical orientation? BON.S DSaddrV ;yes, compute address for vertical ; DSaddrH ADD.W WRhomeof(A0),D5 ; MOVE.W D5,D7 ; ANDI.W #$F,D7 ; ASR.W #4,D5 ; ASL.W #1,D5 ; SUBA.W D5,A4 ; MULU CPscnofs.W,D6 ; SUBA.L D6,A4 ; RTS ;return ; DSaddrV ADD.W WRhomeof(A0),D6 ; MOVE.W D6,D7 ; ANDI.W #$F,D7 ; ASR.W #4,D6 ; ASL.W #1,D6 ; ADDA.W D6,A4 ; MULU CPscnofs.W,D5 ; SUBA.L D5,A4 ; RTS ;return page ; ; jump tables ; DScTbl DATA.W DScrsL-DScTbl ;ctl-H: back space DATA.W DStab-DScTbl ;ctl-I: tab DATA.W DScrsD-DScTbl ;ctl-J: line feed DATA.W DScrsU-DScTbl ;ctl-K: cursor up DATA.W DScrsR-DScTbl ;ctl-L: cursor right DATA.W DSrtrn-DScTbl ;ctl-M: carriage return DSeTbl DATA.W $48,DScrsH-DSeTbl ;esc-H: home cursor DATA.W $4A,DSclAL-DSeTbl ;esc-J: clear screen DATA.W $4B,DSclEL-DSeTbl ;esc-K: clear to end of line DATA.W $59,DSclES-DSeTbl ;esc-Y: clear to end of screen DATA.W -1 ;end of table DSsTbl DATA.W DSst0-DSsTbl ;state 0 DATA.W DSesc-DSsTbl ;state 1 DSwndH DATA.L DScsetH ;WRcharpt DATA.L DShomeH ;home DATA.L DShomeH ;address DATA.W 0,0,0 ;WRhomeof,WRbasex,WRbasey DATA.W DSmaxXH,DSmaxYH ;right,bottom DATA.W 0,0,0 ;x,y,WRbitofs DATA.W 0,DSmaxYH ;WRgrorgx,WRgrorgy DATA.B 0,$1C ;attr1,attr2 DATA.B 0,WRlength ;state, WRrcdlen DScsetH DATA.L DScsetV+CSdata ;character set record pointer DATA.W DScellY,DScellW ;CSlpch, CSbpch DATA.W 32,90 ;CSfrstch, CSlastch DATA.W $FFFF,$FFC0,0 ;mask, dummy, attribs ; ; use vertical character set data ; page DSwndV DATA.L DScsetV ;WRcharpt DATA.L DShomeV ;home DATA.L DShomeV ;address DATA.W 0,0,0 ;WRhomeof,WRbasex,WRbasey DATA.W DSmaxXV,DSmaxYV ;right,bottom DATA.W 0,0,0 ;x,y,WRbitofs DATA.W 0,DSmaxYV ;WRgrorgx,WRgrorgy DATA.B 0,$1D ;attr1,attr2 DATA.B 0,WRlength ;state, WRrcdlen DScsetV DATA.L DScsetV+CSdata ;character set record pointer DATA.W DScellW,DScellY ;CSlpch, CSbpch DATA.W 32,90 ;CSfrstch, CSlastch DATA.W $003F,$FFFF,256 ;mask, dummy, attribs ; ; vertical character set data ; DATA.B 0,0,0,0,0,0 ; blank DATA.B 0,0,$FD,0,0,0 ; ! DATA.B 0,$E0,0,$E0,0,0 ; " DATA.B $28,$FE,$28,$FE,$28,0 ; # DATA.B $24,$54,$FE,$54,$48,0 ; $ DATA.B $C4,$C8,$10,$26,$46,0 ; % DATA.B $6C,$92,$6A,$04,$0A,0 ; & DATA.B 0,0,$20,$C0,0,0 ; ' DATA.B 0,$38,$44,$82,0,0 ; ( DATA.B 0,0,$82,$44,$38,0 ; ) DATA.B $08,$2A,$1C,$2A,$08,0 ; * DATA.B $08,$08,$3E,$08,$08,0 ; + DATA.B 0,$01,$07,0,0,0 ; , DATA.B $10,$10,$10,$10,$10,0 ; - DATA.B 0,0,$02,0,0,0 ; . DATA.B $04,$08,$10,$20,$40,0 ; / DATA.B $7C,$8A,$92,$A2,$7C,0 ; 0 DATA.B 0,$42,$FE,$02,0,0 ; 1 DATA.B $46,$8A,$92,$92,$62,0 ; 2 DATA.B $84,$82,$92,$B2,$CC,0 ; 3 DATA.B $18,$28,$48,$FE,$08,0 ; 4 DATA.B $E4,$A2,$A2,$A2,$9C,0 ; 5 DATA.B $3C,$52,$92,$92,$1C,0 ; 6 DATA.B $80,$8E,$90,$A0,$C0,0 ; 7 DATA.B $6C,$92,$92,$92,$6C,0 ; 8 DATA.B $62,$92,$92,$94,$78,0 ; 9 DATA.B 0,0,$24,0,0,0 ; : DATA.B 0,$01,$26,0,0,0 ; ; DATA.B 0,$10,$28,$44,$82,0 ; < DATA.B 0,$28,$28,$28,$28,0 ; = DATA.B 0,$82,$44,$28,$10,0 ; > DATA.B $40,$80,$9A,$A0,$40,0 ; ? DATA.B $7C,$82,$9A,$9A,$7A,0 ; @ DATA.B $3E,$48,$88,$48,$3E,0 ; A DATA.B $FE,$92,$92,$92,$6C,0 ; B DATA.B $7C,$82,$82,$82,$44,0 ; C DATA.B $FE,$82,$82,$82,$7C,0 ; D DATA.B $FE,$92,$92,$82,$82,0 ; E DATA.B $FE,$90,$90,$80,$80,0 ; F DATA.B $7C,$82,$8A,$8A,$4C,0 ; G DATA.B $FE,$10,$10,$10,$FE,0 ; H DATA.B 0,$82,$FE,$82,0,0 ; I DATA.B $04,$82,$82,$FC,$80,0 ; J DATA.B $FE,$10,$28,$44,$82,0 ; K DATA.B $FE,$02,$02,$02,$02,0 ; L DATA.B $FE,$40,$30,$40,$FE,0 ; M DATA.B $FE,$20,$10,$08,$FE,0 ; N DATA.B $7C,$82,$82,$82,$7C,0 ; O DATA.B $FE,$90,$90,$90,$60,0 ; P DATA.B $7C,$82,$8A,$84,$7A,0 ; Q DATA.B $FE,$90,$98,$94,$62,0 ; R DATA.B $64,$92,$92,$92,$4C,0 ; S DATA.B $80,$80,$FE,$80,$80,0 ; T DATA.B $FC,$02,$02,$02,$FC,0 ; U DATA.B $F8,$04,$02,$04,$F8,0 ; V DATA.B $FC,$02,$1C,$02,$FC,0 ; W DATA.B $C6,$28,$10,$28,$C6,0 ; X DATA.B $C0,$20,$1E,$20,$C0,0 ; Y DATA.B $86,$8A,$92,$A2,$C2,0 ; Z DATA.W 0