; Copyright 1996 Acorn Computers Ltd ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; ; > $.Source.VduTTX ; Teletext (MODE 7) emulation ; --------------------------- ; Author Tim Dobson ; Started 24-Feb-87 ; ***************************************************************************** ; Teletext control codes TTX_AlphaRed * &01 TTX_AlphaGreen * &02 TTX_AlphaYellow * &03 TTX_AlphaBlue * &04 TTX_AlphaMagenta * &05 TTX_AlphaCyan * &06 TTX_AlphaWhite * &07 TTX_Flash * &08 TTX_Steady * &09 TTX_EndBox * &0A TTX_StartBox * &0B TTX_NormalHeight * &0C TTX_DoubleHeight * &0D TTX_GraphRed * &11 TTX_GraphGreen * &12 TTX_GraphYellow * &13 TTX_GraphBlue * &14 TTX_GraphMagenta * &15 TTX_GraphCyan * &16 TTX_GraphWhite * &17 TTX_Conceal * &18 TTX_Contiguous * &19 TTX_Separated * &1A TTX_BlackBackgd * &1C TTX_NewBackgd * &1D TTX_HoldGraph * &1E TTX_RelGraph * &1F TTXGraphContFontA * TTXSoftFonts +0 ; Contiguous graphics font (&20-&3F) TTXGraphSepaFontA * TTXSoftFonts +&140 ; Separated graphics font (&20-&3F) TTXGraphContFontB * TTXSoftFonts +&280 ; Contiguous graphics font (&60-&7F) TTXGraphSepaFontB * TTXSoftFonts +&3C0 ; Separated graphics font (&60-&7F) ; Bits in the map ; Bits 0-7 8 bit character ; Bit 8 0 => Alpha, 1 => Graphics ; Bit 9 0 => Contiguous, 1 => Separated ; Bit 10 0 => Steady, 1 => Flash ; Bit 11 0 => Release, 1 => Hold ; Bit 12 0 => Reveal, 1 => Conceal ; Bits 13-14 Bit 13 Bit 14 ; 0 0 Single Height ; 1 0 Undefined ; 0 1 Double Height Top ; 1 1 Double Height Bottom ; Bit 15 1 => Pending Start Box ; Bit 16 1 => Pending End Box ; Bits 17-19 Foreground colour ; Bit 20 0 => Unboxed, 1 => Boxed ; Bits 21-23 Background colour ; Bit 24 0 => Unboxed, 1 => Boxed ; Bits 25-29,31 Held graphic ; Bit 30 0 => Held graphic contiguous, 1 => separated MapBit_Char * 1 :SHL: 0 MapBit_Graph * 1 :SHL: 8 MapBit_Separated * 1 :SHL: 9 MapBit_Flash * 1 :SHL: 10 MapBit_Hold * 1 :SHL: 11 MapBit_Conceal * 1 :SHL: 12 MapBit_Bottom * 1 :SHL: 13 MapBit_Double * 1 :SHL: 14 MapBit_PendingStart * 1 :SHL: 15 MapBit_PendingEnd * 1 :SHL: 16 MapBit_ForeMask * 7 :SHL: 17 MapBit_BackMask * 7 :SHL: 21 MapBits_Boxed * (1 :SHL: 20) :OR: (1 :SHL: 24) MapBit_HeldMask * &7F :SHL: 25 MapBit_HeldSeparated * 1 :SHL: 30 MapForeShift * 17 MapBackShift * 21 MapHeldShift * 25 MapBit_Default * (7 :SHL: MapForeShift)+32 ; default at start of line ; ***************************************************************************** ; ; TeletextAlloc - Allocate teletext workspace for pending mode change ; Entered with R0 -> mode workspace ; TeletextAlloc ROUT Entry "r1-r7" ; We allocate one block from the system heap which is large enough to contain: ; * TTXMap: (columns+1)*rows*4 ; * TTXLineStarts: rows*4 ; * TTXDoubleCounts: rows*1 LDR R4, [R0, #wkScrRCol] ADD R4, R4, #2 LDR R5, [R0, #wkScrBRow] ADD R5, R5, #1 MUL R6, R4, R5 MOV R6, R6, LSL #2 ; TTXMap size, TTXLineStarts offset ADD R7, R6, R5, LSL #2 ; TTXMap+TTXLineStarts size, TTXDoubleCounts offset ADD R3, R7, R5 ; Total size BL ClaimSysHeapNode ; Remember new workspace pointer for later STRVC R2, [WsPtr, #TTXNewWorkspace] EXIT ; ***************************************************************************** ; ; TeletextInit - Initialise teletext workspace ; Called when MODE 7 (or 135) is selected ; TeletextInit ROUT Entry ; Claim the workspace that was previously allocated by TeletextAlloc LDR R2, [WsPtr, #TTXNewWorkspace] TEQ R2, #0 BEQ %FT05 ; If there's no pending workspace pointer then VDU output is switching from sprite back to screen and we should skip most of this BL TeletextFinalise ; Ensure old workspace is freed MOV R0, #0 STR R0, [WsPtr, #TTXNewWorkspace] ; Calculate offsets to the different components ; NOTE: TTXFastCLS relies on TTXLineStarts directly following TTXMap LDR R4, [WsPtr, #ScrRCol] ADD R4, R4, #2 LDR R5, [WsPtr, #ScrBRow] ADD R5, R5, #1 MUL R6, R4, R5 MOV R6, R6, LSL #2 ; TTXMap size, TTXLineStarts offset ADD R7, R6, R5, LSL #2 ; TTXMap+TTXLineStarts size, TTXDoubleCounts offset ; Fill in the pointers STR R2, [WsPtr, #TTXMapPtr] ADD R6, R2, R6 STR R6, [WsPtr, #TTXLineStartsPtr] ADD R7, R2, R7 STR R7, [WsPtr, #TTXDoubleCountsPtr] ; Initialise TTXLineStarts ; Everything else is initialised later on 01 STR R2, [R6], #4 ADD R2, R2, R4, LSL #2 TEQ R6, R7 BNE %BT01 05 MOV R0, #1 ; set to flash immediately STR R0, [WsPtr, #TeletextCount] MOV R0, #TTXFlag_Conceal ORR R0, R0, #TTXFlag_FgTransBIC :OR: TTXFlag_BgTransBIC STR R0, [WsPtr, #TTXFlags] [ :LNOT: HiResTTX ; compute the graphics fonts ADD R0, WsPtr, #TTXSoftFonts ; R0 -> contiguous font MOV R2, #&20 ; R2 = character number MOV R3, #0 ; R3 = byte to store 10 ADD R1, R0, #&140 ; R1 -> separated font 20 TST R2, #1 ; top left ORRNE R3, R3, #&F0 TST R2, #2 ; top right ORRNE R3, R3, #&0F STRB R3, [R0], #1 ; 3 pixel rows for top STRB R3, [R0], #1 STRB R3, [R0], #1 AND R3, R3, #&77 ; do separated STRB R3, [R1], #1 STRB R3, [R1], #1 MOV R3, #0 STRB R3, [R1], #1 TST R2, #4 ; middle left ORRNE R3, R3, #&F0 TST R2, #8 ; middle right ORRNE R3, R3, #&0F STRB R3, [R0], #1 ; 4 pixel rows for middle STRB R3, [R0], #1 STRB R3, [R0], #1 STRB R3, [R0], #1 AND R3, R3, #&77 ; do separated STRB R3, [R1], #1 STRB R3, [R1], #1 STRB R3, [R1], #1 MOV R3, #0 STRB R3, [R1], #1 TST R2, #&10 ; bottom left ORRNE R3, R3, #&F0 TST R2, #&40 ; bottom right ORRNE R3, R3, #&0F STRB R3, [R0], #1 ; 3 pixel rows for bottom STRB R3, [R0], #1 STRB R3, [R0], #1 AND R3, R3, #&77 ; do separated STRB R3, [R1], #1 STRB R3, [R1], #1 MOV R3, #0 STRB R3, [R1], #1 ADD R2, R2, #1 TEQ R2, #&40 ; if at end of 1st part MOVEQ R2, #&60 ; then start 2nd ADDEQ R0, R0, #&140 ; skipping separated already done BEQ %BT10 ; and resetting R1 too TEQ R2, #&80 ; finished BNE %BT20 ] EXIT ; ***************************************************************************** ; ; TeletextFinalise - Free teletext workspace ; Called when switching out of teletext mode ; TeletextFinalise ROUT Entry "r0-r2" ; TTXMapPtr is the pointer to the allocated block LDR R2, [WsPtr, #TTXMapPtr] CMP R2, #0 BLNE FreeSysHeapNode MOV R0, #0 STR R0, [WsPtr, #TTXMapPtr] STR R0, [WsPtr, #TTXLineStartsPtr] STR R0, [WsPtr, #TTXDoubleCountsPtr] CLRV EXIT ; ***************************************************************************** ; ; Vdu23_18 - Miscellaneous Teletext operations ; Vdu23_18 LDRB R2, [WsPtr, #QQ+1] CMP R2, #(Vdu23_18_TabEnd - Vdu23_18_TabStart) / 4 BCS UnknownVdu23 LDR R0, [WsPtr, #CursorFlags] TST R0, #TeletextMode ADDNE PC, PC, R2, LSL #2 MOV PC, LR Vdu23_18_TabStart B Vdu23_18_0 B Vdu23_18_1 B Vdu23_18_2 B Vdu23_18_3 Vdu23_18_TabEnd ; ***************************************************************************** ; ; Vdu23_18_0 - Set transparency ; Vdu23_18_0 ROUT Push "R14" LDRB R5, [WsPtr, #QQ+2] AND R5, R5, #3 LDR R6, [WsPtr, #TTXFlags] AND R14, R6, #TTXFlag_TransModeMask TEQ R14, R5, LSL #TTXFlag_TransModeShift Pull "PC", EQ ; fast exit if nothing's changed ; Because the border is being reprogrammed, switches in and out of mode 0 (solid) ; look messy unless we reprogram the palette too (on the non-solid side of the switch) TEQ R5, #0 ; switching into mode 0? ADREQ R2, TTXPalette_Solid ; if so, program a solid palette MOVEQ R7, #0 ; use a black border BLEQ SetTTXPalette ; Munge the TTXFlags to match the transparency mode ORR R6, R6, #TTXFlag_FgTransEOR :OR: TTXFlag_BgTransEOR ORR R6, R6, #TTXFlag_FgTransBIC :OR: TTXFlag_BgTransBIC TEQ R5, #3 ; already adjusted for mode 3 (transparent) BEQ %FT10 TEQ R5, #2 ; in modes 0 (solid) and 1 (mix) BICNE R6, R6, #TTXFlag_FgTransEOR ; we just clear the fg transparency bit BICEQ R6, R6, #TTXFlag_FgTransBIC ; in mode 2 (box) we just toggle it TEQ R5, #0 ; in modes 1 (mix) and 2 (box) BICNE R6, R6, #TTXFlag_BgTransBIC ; we just toggle the bg transparency bit BICEQ R6, R6, #TTXFlag_BgTransEOR ; in mode 0 (solid) we just clear it 10 ; Move the mode bits from TTXFlags to R7, and then from R5 to TTXFlags MOV R7, R6 BIC R6, R6, #TTXFlag_TransModeMask ORR R6, R6, R5, LSL #TTXFlag_TransModeShift STR R6, [WsPtr, #TTXFlags] ; Redraw the screen (paletted case) Push "R7" LDR R7, [WsPtr, #Log2BPP] CMP R7, #3 BLLS RefreshBitmap Pull "R7" ; Deal with the opposite palette programming case (switching away from mode 0) TST R7, #TTXFlag_TransModeMask ADREQ R2, TTXPalette_Mixed ; use a mixed palette for all other modes MOVEQ R7, #&FF ; and they all have a transparent border, too BLEQ SetTTXPalette ; Redraw the screen (true colour case) LDR R7, [WsPtr, #Log2BPP] CMP R7, #3 MOVHI R7, #-1 STRHI R7, [WsPtr, #TForeCol] ; ensure TTXUpdateColours gets called on next char plot BLHI RefreshBitmap Pull "PC" SetTTXPalette Push "R14" LDR R0, [WsPtr, #Log2BPP] CMP R0, #3 BHI %FT20 ; Set 1st flash states MOV R0, #0 ; start at colour 0 MOV R1, #16 ; program 16 colours ORR R1, R1, #17:SHL:24 ; program 1st flash state MOV R4, #paletteV_BulkWrite BL CallPaletteV ; Set 2nd flash states MOV R0, #0 ; start at colour 0 MOV R1, #16 ; program 16 colours ORR R1, R1, #18:SHL:24 ; program 2nd flash state MOV R4, #paletteV_BulkWrite BL CallPaletteV 20 ; Set up the border colour MOV R0, #0 ; logical colour 0 MOV R1, #24 ; type 24 (border) MOV R2, R7 ; palette entry passed in R7 MOV R4, #paletteV_Set BL CallPaletteV Pull "PC" TTXPalette_Solid & &00000000 ; black & &0000FF00 ; red & &00FF0000 ; green & &00FFFF00 ; yellow & &FF000000 ; blue & &FF00FF00 ; magenta & &FFFF0000 ; cyan & &FFFFFF00 ; white TTXPalette_Mixed & &00000000 ; black & &0000FF00 ; red & &00FF0000 ; green & &00FFFF00 ; yellow & &FF000000 ; blue & &FF00FF00 ; magenta & &FFFF0000 ; cyan & &FFFFFF00 ; white & &000000FF ; transparent & &0000FFFF ; transparent & &00FF00FF ; transparent & &00FFFFFF ; transparent & &FF0000FF ; transparent & &FF00FFFF ; transparent & &FFFF00FF ; transparent & &FFFFFFFF ; transparent ; ***************************************************************************** ; ; Vdu23_18_1 - Suspend/resume bitmap updates ; Vdu23_18_1 ROUT Push "R14" LDRB R0, [WsPtr, #QQ+2] LDR R1, [WsPtr, #TTXFlags] TST R0, #1 ; bit 0 of 3rd parameter BICEQ R2, R1, #TTXFlag_Suspend ; determines new setting of suspend flag ORRNE R2, R1, #TTXFlag_Suspend STR R2, [WsPtr, #TTXFlags] BICS R14, R1, R2 ; if coming out of suspension BLNE RefreshBitmap ; then redraw screen Pull "PC" ; ***************************************************************************** ; ; Vdu23_18_2 - Reveal/conceal ; Vdu23_18_2 ROUT Push "R14" LDRB R0, [WsPtr, #QQ+2] LDR R1, [WsPtr, #TTXFlags] TST R0, #1 ; bit 0 of 3rd parameter ORREQ R1, R1, #TTXFlag_Conceal ; determines new setting of reveal flag BICNE R1, R1, #TTXFlag_Conceal STR R1, [WsPtr, #TTXFlags] TST R1, #TTXFlag_Suspend ; unless suspended, BLEQ RefreshBitmap ; redraw the screen Pull "PC" ; ***************************************************************************** ; ; Vdu23_18_3 - Enable/disable black foreground control codes ; Vdu23_18_3 ROUT Push "R14" LDRB R0, [WsPtr, #QQ+2] LDR R1, [WsPtr, #TTXFlags] TST R0, #1 ; bit 0 of 3rd parameter BICEQ R2, R1, #TTXFlag_BlackEnable ; determines new setting of blackenable flag ORRNE R2, R1, #TTXFlag_BlackEnable EOR R1, R1, R2 TST R1, #TTXFlag_BlackEnable ; has blackenable changed? Pull "PC", EQ ; if not, then exit Push "R2" ; save R2 for later ORR R2, R2, #TTXFlag_Suspend ; temporarily suspend bitmap update STR R2, [WsPtr, #TTXFlags] MOV R0, #0 ; start at left MOV R1, #0 ; start at top LDR R2, [WsPtr, #TTXMapPtr] ; R2 -> start of map ADD R7, R2, #4*1 ; R7 -> map entry for first real char LDR R5, [WsPtr, #ScrRCol] ADD R5, R7, R5, LSL #2 ; R5 -> map entry for last char on first line MOV R11, #0 ; R11 = top line LDR R10, [WsPtr, #ScrBRow] ADD R10, R10, #1 ; R10 = bottom line + 1 ADR R14, %FT50 Push "R14" ; set up return address on stack B TTXScanZap2 ; recalculate the map 50 Pull "R2" ; retrieve the final TTXFlags STR R2, [WsPtr, #TTXFlags] ; save them TST R2, #TTXFlag_Suspend ; and unless we were suspended on entry BLEQ RefreshBitmap ; then redraw the screen Pull "PC" ; ***************************************************************************** ; ; RefreshBitmap - Brings bitmap up-to-date with TTXMap ; RefreshBitmap ROUT Entry "R9-R11" MOV R0, #0 MOV R1, #0 BL AddressR0R1 ; R2 -> top-left character in bitmap LDR R7, [WsPtr, #RowLength] LDR R11, [WsPtr, #CharWidth] LDR R8, [WsPtr, #ScrRCol] MLA R8, R11, R8, R11 SUB R7, R7, R8 ; R7 = offset from end of one row to start of next LDR R8, [WsPtr, #TTXLineStartsPtr] MOV R6, #0 ; R6 is line number: 0 <= R11 <= 24 LDR R10, [WsPtr, #ScrBRow] 10 LDR R4, [R8, R6, LSL #2] ; R4 -> map entry for magic 0th character LDR R5, [WsPtr, #ScrRCol] ADD R5, R5, #1 ADD R5, R4, R5, LSL #2 ; R5 -> last map entry on line 20 LDR R1, [R4], #4 ; load map entry for previous character LDR R0, [R4] ; load map entry for current character BIC R1, R1, #&FF AND R0, R0, #&FF ORR R0, R1, R0 ; construct R0 and R1 as required by DoPreControl AND R1, R0, #&7F CMP R1, #&20 ; is it a control char BLCC DoPreControl ; [do pre-control things] BL UpdateHeldBits BL TTXPaintChar ; paint it to the screen ADD R2, R2, R11 CMP R4, R5 BCC %BT20 ADD R2, R2, R7 ; and drop down to start of next line ADD R6, R6, #1 CMP R6, R10 BLS %BT10 EXIT [ HiResTTX ; ***************************************************************************** ; ; ComputeGraphic - Called on a character-by-character basis ; Generates a graphic character on the fly ; ; in: R1 -> space to build character in ; R3 = character: bits 0-4,6 are block flags, bit 5 is separated flag ; ; out: Character built in R1 ; All regs preserved ; ComputeGraphic ROUT Push "R1,mask,R10,R14" MOV mask, #&FF000000 ORR mask, mask, mask, LSR #16 ; mask for setting left-hand blocks (shift for right-hand) MOV R10, #&C0000000 ORR R10, R10, R10, LSR #16 ORR R10, R10, R10, LSR #8 ; mask for separated graphics vertical lines MOV R14, #0 ; holds each word of the character as we build it up TST R3, #1:SHL:0 ORRNE R14, R14, mask TST R3, #1:SHL:1 ORRNE R14, R14, mask, LSR #8 TST R3, #1:SHL:5 BICNE R14, R14, R10 STR R14, [R1], #4 ; first 4 lines identical STR R14, [R1], #4 MOVNE R14, #0 ; if separated, then 2 horizontal lines, else same as above STR R14, [R1], #4 MOV R14, #0 TST R3, #1:SHL:2 ORRNE R14, R14, mask TST R3, #1:SHL:3 ORRNE R14, R14, mask, LSR #8 TST R3, #1:SHL:5 BICNE R14, R14, R10 STR R14, [R1], #4 ; 8 lines total for middle blocks STR R14, [R1], #4 STR R14, [R1], #4 MOVNE R14, #0 STR R14, [R1], #4 MOV R14, #0 TST R3, #1:SHL:4 ORRNE R14, R14, mask TST R3, #1:SHL:6 ORRNE R14, R14, mask, LSR #8 TST R3, #1:SHL:5 BICNE R14, R14, R10 STR R14, [R1], #4 ; 6 lines total for bottom blocks STR R14, [R1], #4 MOVNE R14, #0 STR R14, [R1], #4 Pull "R1,mask,R10,PC" ] ; ***************************************************************************** ; ; TTXFastCLS - Called when clearing whole screen ; Clears the teletext map to default ; TTXFastCLS ROUT LDR R0, [WsPtr, #TTXMapPtr] ; R0 -> map LDR R1, [WsPtr, #TTXLineStartsPtr] ; R1 -> end of map LDR R2, =MapBit_Default ; R2 = default status at start of line 10 STR R2, [R0], #4 CMP R0, R1 BLO %BT10 LDR R0, [WsPtr, #TTXDoubleCountsPtr] ; zero double counts on each line LDR R1, [WsPtr, #ScrBRow] ADD R1, R1, #1 ADD R1, R1, R0 MOV R2, #0 20 STRB R2, [R0], #1 TEQ R0, R1 BNE %BT20 MOV PC, R14 ; ***************************************************************************** ; ; TTXUpdateColours - Update colour table for new colours ; ; in: R5 = new foregd colour ; R6 = new backgd colour ; ; out: R0, R2 preserved ; TTXUpdateColours ROUT Push "R0,R2,R14" ADD R14, WsPtr, #TForeCol STMIA R14, {R5,R6} MOV fore, R5 MOV back, R6 LDR bpp, [WsPtr, #BitsPerPix] [ HiResTTX CMP bpp, #8 BLS %FT10 ; Convert colour index to pixel value ADRL R14, TTXPalette_Solid LDR R0, [R14, fore, LSL #2] LDR back, [R14, back, LSL #2] SWI XColourTrans_ReturnColourNumber MOV fore, R0 MOV R0, back SWI XColourTrans_ReturnColourNumber ; Fixup the supremacy/alpha channel if necessary ; (ColourTrans always sets it to default!) TST R5, #8 TSTEQ R6, #8 LDRNE R14, [WsPtr, #TTXFlags] TSTNE R14, #TTXFlag_TransModeMask BEQ %FT09 Push "fore" BL GetAlphaSupremacyBits Pull "fore" TST R5, #8 EORNE fore, fore, back TST R6, #8 EORNE R0, R0, back 09 MOV back, R0 LDR bpp, [WsPtr, #BitsPerPix] ; (R0) 10 ] BL SetColours Pull "R0,R2,PC" [ :LNOT: HiResTTX ; ***************************************************************************** ; ; PrintDoubleHeight - Process font for double height ; ; in: R0 = char + attributes ; tophalf contains bytes 0123 ; bottomhalf contains bytes 4567 ; R10 contains bytes xx89 ; We know that at least one of MapBit_Bottom or MapBit_Double is set ; ; out: tophalf, bottomhalf, R10 updated ; R3 corrupted ; PrintDoubleHeight ROUT TST R0, #MapBit_Double ; if not double height, MOVEQ tophalf, #0 ; then must be single height MOVEQ bottomhalf, #0 ; part on line below double, MOVEQ R10, #0 ; so make it invisible MOVEQ PC, R14 TST R0, #MapBit_Bottom BNE %FT10 ; [bottom half of double] [ 1=1 ; 0 1 2 3 4 ; do top half, we want tophalf=0112, bottomhalf=2334, R10=xx45 MOV R10, bottomhalf, LSL #16 ; R10 := o o 4 5 ORR R10, R10, R10, LSL #8 ; R10 := o o 4 4/5 AND R3, tophalf, #&FF000000 ; R3 := o o o 3 ORR bottomhalf, R3, bottomhalf, LSL #24 ; bot := o o o 3/4 MOV R3, tophalf, LSR #16 ; R3 := 2 3 o o ORR R3, R3, R3, LSL #8 ; R3 := 2 2/3 3 o ORR bottomhalf, bottomhalf, R3 ; bot := 2 2/3 3 3/4 MOV tophalf, tophalf, LSL #16 ; top := o o 0 1 ORR tophalf, tophalf, tophalf, LSR #8 ; top := o 0 0/1 1 MOV tophalf, tophalf, LSR #8 ; top := 0 0/1 1 o ORR tophalf, tophalf, bottomhalf, LSL #24 ; top := 0 0/1 1 2 AND R3, tophalf, #&00FF0000 ; R3 := o o 1 o ORR tophalf, tophalf, R3, LSL #8 ; top := 0 0/1 1 1/2 MOV PC, R14 10 ; 5 6 7 8 9 ; do bottom half, we want tophalf=5667, bottomhalf=7889, R10=xx9o AND tophalf, bottomhalf, #&FF000000 ; top := o o o 7 MOV R3, bottomhalf, LSL #8 ; R3 := o 4 5 6 MOV R3, R3, LSR #16 ; R3 := 5 6 o o ORR tophalf, tophalf, R3 ; top := 5 6 o 7 ORR tophalf, tophalf, R3, LSL #8 ; top := 5 5/6 6 7 AND R3, R3, #&0000FF00 ; R3 := o 6 o o ORR tophalf, tophalf, R3, LSL #16 ; top := 5 5/6 6 6/7 MOV bottomhalf, bottomhalf, LSR #24 ; bot := 7 o o o AND R3, R10, #&00FF0000 ; R3 := o o 8 o ORR bottomhalf, bottomhalf, R3, LSR #8 ; bot := 7 8 o o ORR bottomhalf, bottomhalf, bottomhalf, LSL #8 ; bot := 7 7/8 8 o ORR R3, R10, R10, LSL #8 ; R3 := x x x 8/9 AND R3, R3, #&FF000000 ; R3 := o o o 8/9 ORR bottomhalf, bottomhalf, R3 ; bot := 7 7/8 8 8/9 MOV R10, R10, LSR #24 ; R10 := 9 o o o ORR R10, R10, R10, LSL #8 ; R10 := 9 9 o o MOV R10, R10, LSL #16 ; R10 := o o 9 9 MOV PC, R14 | ; do top half, we want tophalf=0011, bottomhalf=2233, R10=xx44 MOV R10, bottomhalf, LSL #24 ; R10 := ooo4 ORR R10, R10, R10, LSR #8 ; R10 := oo44 AND bottomhalf, tophalf, #&00FF0000 ; bottom := oo2o ORR bottomhalf, bottomhalf, tophalf, LSR #24 ; bottom := 3o2o ORR bottomhalf, bottomhalf, bottomhalf, LSL #8 ; bottom := 3322 MOV bottomhalf, bottomhalf, ROR #16 ; bottom := 2233 AND R3, tophalf, #&0000FF00 ; R3 := o1oo AND tophalf, tophalf, #&FF ; top := 0ooo ORR tophalf, tophalf, R3, LSL #8 ; top := 0o1o ORR tophalf, tophalf, tophalf, LSL #8 ; top := 0011 MOV PC, R14 ; do bottom half, we want tophalf=5566, bottomhalf=7788, R10=xx99 10 AND tophalf, bottomhalf, #&0000FF00 ; top := o5oo MOV bottomhalf, bottomhalf, LSR #16 ; bot := 67oo ORR tophalf, tophalf, bottomhalf, LSL #24 ; top := o5o6 ORR tophalf, tophalf, tophalf, LSR #8 ; top := 5566 MOV bottomhalf, bottomhalf, LSR #8 ; bot := 7ooo MOV R10, R10, LSR #16 ; R10 := 89oo ORR bottomhalf, bottomhalf, R10, LSL #16 ; bot := 7o89 BIC bottomhalf, bottomhalf, #&FF000000 ; bot := 7o8o ORR bottomhalf, bottomhalf, bottomhalf, LSL #8 ; bot := 7788 BIC R10, R10, #&FF ; R10 := o9oo ORR R10, R10, R10, LSR #8 ; R10 := 99oo MOV R10, R10, LSL #16 ; R10 := oo99 MOV PC, R14 ] ] ; ***************************************************************************** ; ; TTXWrch - Print a character in the range &20-&FF ; ; in: R0 = character ; out: cursor has been moved on if appropriate ; TTXWrch ROUT Push R14 BL TTXDoChar Pull R14 B PostCharMove ; ***************************************************************************** ; ; TTXDoChar - Print a character (don't move cursor) ; ; in: R0 = character ; TTXDoChar ROUT Push R14 MOV R3, R0 TEQ R3, #"#" ; swap around the three MOVEQ R0, #"_" ; old favourites TEQ R3, #"_" MOVEQ R0, #"`" TEQ R3, #"`" MOVEQ R0, #"#" LDR R11, [WsPtr, #CursorY] ; R11 = current Y position LDR R3, [WsPtr, #CursorX] ; R3=start X posn on this line LDR R2, [WsPtr, #CursorAddr] ; screen address TTXScanFromHere MOV R4, #0 ; Xmin and MOV R5, #0 ; Xmax are irrelevant MOV R10, #0 ; Ymax always <= Y so no zap ; ; TTXScanZap - Plot multiple characters from map, or plot spaces ; ; in: R0 = current (initial) character ; R2 = current screen addr ; R3 = current X ; R4 = X min of area ; R5 = X max of area ; R10 = Y max of area ; R11 = current Y ; R12 -> VDU workspace ; R14 = non-zero to plot from map, zero to plot spaces ; Return address stacked ; ; out: R0-R11 corrupt ; TTXScanZap LDR R1, [WsPtr, #TTXLineStartsPtr] ; R1 -> table of line starts LDR R8, [R1, R11, LSL #2] ; R8 -> map entry at st.of line LDR R7, [WsPtr, #ScrRCol] ADD R7, R7, #1 ADD R7, R8, R7, LSL #2 ; R7 -> end of this line LDR R1, [R8, R3, LSL #2]! ; R1 = prev. char+attr LDR R6, [WsPtr, #CharWidth] 08 LDR R3, [WsPtr, #TTXDoubleCountsPtr] LDRB R9, [R3, R11] ; R9 = no. of dbls on this line 10 BIC R1, R1, #&FF ; clear char bits ORR R0, R1, R0 ; store new char AND R1, R0, #&7F ; just look at char bits Push R14 CMP R1, #&20 ; is it a control char BLCC DoPreControl ; [do pre-control things] BL UpdateHeldBits ; this needs doing irrespective of suspension LDR R14, [WsPtr, #TTXFlags] TST R14, #TTXFlag_Suspend BLEQ TTXPaintChar BIC R0, R0, #(MapBit_PendingStart :OR: MapBit_PendingEnd) CMP R1, #&20 BLCC DoPostControl ; [do post-control things] Pull R14 ; restore zap flag LDR R1, [R8, #4]! ; get old character STR R0, [R8] ; store character away AND R3, R1, #&7F ; if overwriting double height TEQ R3, #TTX_DoubleHeight SUBEQ R9, R9, #1 ; then one less EOR R1, R0, R1 ; get difference BIC R3, R1, #&FF ; difference in attributes MOV R1, R0 ; R1 = prev char + new attr CMP R11, R10 ; if Y >= Ymax BCS %FT20 ; then load from map CMPCC R8, R5 ; else if X <= Xmax MOVLS R3, #1 ; then pretend attr different CMPCC R4, R8 ; if Xmin < X < Xmax CMPCC R14, #1 ; and we're zapping (not scan) MOVCC R0, #32 ; then zap to space 20 LDRCSB R0, [R8, #4] ; else load from map TEQ R3, #0 ; if attributes different TEQNE R8, R7 ; and not at end of line ADDNE R2, R2, R6 ; then move to next char BNE %BT10 ; and loop LDR R3, [WsPtr, #TTXDoubleCountsPtr] STRB R9, [R3, R11] ; update no. of doubles LDR R3, [WsPtr, #ScrBRow] TEQ R11, R3 ADD R11, R11, #1 ; go to next line Pull PC, EQ ; if off bottom of screen then finished MOVS R3, R9 ; if no doubles ; then next line is top line EORNE R3, R1, #MapBit_Bottom ; else next line is opposite ; to this line LDR R1, [R7, #4] ; get dummy word on next line EOR R3, R1, R3 ; difference ANDS R3, R3, #MapBit_Bottom ; difference in 'bottom' bit EORNE R1, R1, #MapBit_Bottom ; if different then toggle bit STR R1, [R7, #4]! ; always store back BNE %FT30 ; and do another row CMP R11, R10 ; else if finished zap Pull PC, CS ; then exit 30 ; now compute new R2 SUB R3, R7, R8 ; (no. of chars before eol) * 4 LDR R9, [WsPtr, #ScrRCol] ADD R9, R9, #1 RSB R3, R3, R9, LSL #2 ; (current char number) * 4 MUL R3, R6, R3 ; (number of bytes) * 4 SUB R2, R2, R3, LSR #2 ; back to start of old line LDR R3, [WsPtr, #RowLength] ADD R2, R2, R3 ; move down a row MOV R8, R7 ; R8 -> dummy char on new line ADD R7, R7, R9, LSL #2 ; R7 -> last char on new line ADD R9, R9, #1 ADD R4, R4, R9, LSL #2 ; move Xmin to next line ADD R5, R5, R9, LSL #2 ; move Xmax to next line CMP R11, R10 ; if Y < Ymax CMPCC R8, R5 ; and X < Xmax CMPCC R4, R8 ; if also Xmin < X CMPCC R14, #1 ; & we're zapping not scanning MOVCC R0, #32 ; then zap to space LDRCSB R0, [R8, #4] ; else load from map B %BT08 ; ***************************************************************************** ; ; TTXClearBox - Fill a rectangle with spaces, and update screen ; ; in: R0 = left column ; R1 = bottom row ; R2 = right column ; R3 = top row ; Return address already stacked ; TTXClearBox ADD R10, R1, #1 ; R10 := bottom +1 MOV R11, R3 ; R11 := top ADD R5, R2, #1 ; R5 := right + 1 MOV R1, R3 BL AddressR0R1 ; R2 := address(topleft) ; R1, R3, R4 corrupted MOV R3, R0 ; R3 := left LDR R4, [WsPtr, #TTXLineStartsPtr] LDR R0, [R4, R11, LSL #2] ; R0 -> dummy(top) ADD R5, R0, R5, LSL #2 ; R5 := map(topright) ADD R4, R0, R3, LSL #2 ; R4 := map(topleft)-4 SUB R4, R4, #4 ; R4 := map(topleft)-8 MOV R0, #32 ; start with a space MOV R14, #0 ; indicate zapping B TTXScanZap ; go and do it ; ***************************************************************************** ; ; TTXHardScrollUp - Scroll teletext screen upwards ; TTXHardScrollUp ROUT ; first scroll map up LDR R0, [WsPtr, #RowLength] ; save real RowLength Push "R0, R6, R14" ; and save CursorFlags MOV R0, #1 ; pretend rowmult = 1 LDR R2, [WsPtr, #TTXMapPtr] ; R2 -> TTXMap LDR R5, [WsPtr, #ScrRCol] ADD R5, R5, #2 MOV R5, R5, LSL #2 ; R5 = no. of bytes horiz STR R5, [WsPtr, #RowLength] ; pretend rowlength LDR R6, [WsPtr, #ScrBRow] ; no. of 'pixel' rows MOV R7, R5 ; linelength ADD R6, R6, #1 BL SoftScrollUp2 Pull "R0, R6" STR R0, [WsPtr, #RowLength] ; restore RowLength ; now 'scroll' DoubleCounts LDR R0, [WsPtr, #TTXDoubleCountsPtr] LDR R1, [WsPtr, #ScrBRow] ADD R1, R0, R1 10 LDRB R2, [R0, #1] STRB R2, [R0], #1 TEQ R0, R1 BNE %BT10 ; now see if top line was a 'bottom' row ; if so, we need to rescan from the top LDR R8, [WsPtr, #TTXMapPtr] ; R8 -> top left map LDR R1, [R8] ; R1 = dummy word TST R1, #MapBit_Bottom ; if not bottom BEQ %FT20 ; then OK BIC R1, R1, #MapBit_Bottom ; make into a 'top' line STR R1, [R8] ; store back LDRB R0, [R8, #4] ; R0 = first char MOV R3, #0 ; X = 0 MOV R11, #0 ; Y = 0 LDR R2, [WsPtr, #ScreenStart] ; screen address for top-left LDR R14, [WsPtr, #TextOffset] ; plus the offset ADD R2, R2, R14 ADR R14, %FT20 Push R14 B TTXScanFromHere 20 ; now see if new bottom line should be a 'bottom' or a 'top' line LDR R1, [WsPtr, #ScrBRow] SUB R1, R1, #1 LDR R0, [WsPtr, #TTXLineStartsPtr] LDR R0, [R0, R1, LSL #2] ; R0 -> dummy word on line 23 LDR R14, [WsPtr, #TTXDoubleCountsPtr] LDRB R1, [R14, R1] ; no. of dbls on line 23 TEQ R1, #0 ; if R1=0 then line 24 is 'top' LDRNE R1, [R0] ; else line 24 is opposite EORNE R1, R1, #MapBit_Bottom ; of line 23 ANDNE R1, R1, #MapBit_Bottom LDR R14, [WsPtr, #ScrRCol] ADD R14, R14, #2 LDR R2, [R0, R14, LSL #2] ; R2 = dummy word on line 24 BIC R2, R2, #MapBit_Bottom ; clear that bit ORR R2, R2, R1 ; OR in new bit STR R2, [R0, R14, LSL #2] ; and store back Pull PC ; ***************************************************************************** ; ; TTXSoftScrollUp - Scroll screen up by software in teletext mode ; TTXSoftScrollUp ROUT ; first scroll map up LDR R0, [WsPtr, #RowLength] ; save real RowLength LDR R1, [WsPtr, #TWTRow] ; top row LDR R3, [WsPtr, #TWBRow] ; bottom row LDR R2, [WsPtr, #TTXLineStartsPtr] LDR R2, [R2, R1, LSL #2] ; R2 -> dummy char top row ADD R2, R2, #4 ; R2 -> 0th char top row LDR R4, [WsPtr, #TWLCol] LDR R5, [WsPtr, #TWRCol] Push "R0-R6,R14" ; and save CursorFlags ADD R2, R2, R4, LSL #2 ; R2 -> top left char SUB R5, R5, R4 ADD R5, R5, #1 ; R5 = no. of chars wide MOV R5, R5, LSL #2 ; R5 = no. of bytes / line SUB R6, R3, R1 ADD R6, R6, #1 ; R6 = no. of 'pixel' rows LDR R7, [WsPtr, #ScrRCol] ADD R7, R7, #2 MOV R7, R7, LSL #2 ; R7 = line length STR R7, [WsPtr, #RowLength] ; pretend row length MOV R0, #1 ; pretend rowmult =1 BL SoftScrollUp2 Pull "R0-R6" STR R0, [WsPtr, #RowLength] ; restore RowLength ; now R1=top row, R2 -> char 0 on row R1, R3=bottom row, R4=left, R5=right ; now clear bottom row LDR R7, [WsPtr, #TTXLineStartsPtr] LDR R7, [R7, R3, LSL #2] ; R7 -> dummy word(bottom) ADD R8, R7, R5, LSL #2 ; R8 -> char before bottom rt ADD R7, R7, R4, LSL #2 ; R7 -> char before bottom left MOV R0, #32 30 STRB R0, [R7, #4]! ; zap to space CMP R7, R8 ; if <= char before bottom rt BLS %BT30 ; then loop MOV R9, R2 CountAndRescan BL CountDoubles ; now rescan from top of window ADD R10, R3, #1 ; R10 = bottom + 1 MOV R11, R1 ; R11 = top ADD R7, R2, R4, LSL #2 ; R7 = map(left,top) ADD R5, R2, R5, LSL #2 ; R5 = map(right,top) MOV R0, R4 ; R0 = left TTXScanZap2 BL AddressR0R1 ; R2 = screen(left,top) ; (R1,R3,R4 corrupted) SUB R4, R7, #8 ; R4 = map(left,top)-8 MOV R3, R0 ; R3 = left LDRB R0, [R4, #8] ; R0 = first char MOV R14, #1 ; scan not zap B TTXScanZap ; ***************************************************************************** ; ; CountDoubles - Count double height characters in a range of rows ; ; in: R1 = top row to count ; R3 = bottom row to count ; R9 -> map(0,top) ; ; out: R1-R6 preserved ; CountDoubles ROUT Entry LDR R7, [WsPtr, #TTXDoubleCountsPtr] ADD R7, R7, R1 ; R7 -> current double count MOV R11, R1 LDR R14, [WsPtr, #ScrRCol] ADD R14, R14, #1 10 ADD R8, R9, R14, LSL #2 ; R8 -> dummy char next row MOV R10, #0 ; count so far 20 LDR R0, [R9], #4 ; load char word AND R0, R0, #&7F ; only look at bottom 7 bits TEQ R0, #TTX_DoubleHeight ; if double height ADDEQ R10, R10, #1 ; then increment count TEQ R9, R8 ; if not at end of row BNE %BT20 ; then loop STRB R10, [R7], #1 ; store double count ADD R9, R9, #4 ; skip dummy char ADD R11, R11, #1 ; goto next row CMP R11, R3 ; if <= bottom BLS %BT10 ; then loop EXIT ; ***************************************************************************** ; ; TTXHardScrollDown - Scroll teletext screen downwards ; TTXHardScrollDown ROUT ; first scroll map down LDR R0, [WsPtr, #RowLength] ; save real RowLength Push "R0, R6, R14" ; and save CursorFlags MOV R0, #1 ; pretend rowmult = 1 LDR R6, [WsPtr, #ScrBRow] LDR R2, [WsPtr, #TTXLineStartsPtr] LDR R2, [R2, R6, LSL #2] ; R2 -> dummy char on bottom LDR R5, [WsPtr, #ScrRCol] ADD R5, R5, #2 MOV R5, R5, LSL #2 ; R5 = no. of bytes horiz STR R5, [WsPtr, #RowLength] ; pretend rowlength ADD R6, R6, #1 ; no. of 'pixel' rows MOV R7, R5 ; linelength BL SoftScrollDown2 SUB R14, R6, #1 Pull "R0, R6" STR R0, [WsPtr, #RowLength] ; restore RowLength ; now 'scroll' DoubleCounts LDR R0, [WsPtr, #TTXDoubleCountsPtr] ADD R1, R0, R14 10 LDRB R2, [R1, #-1] STRB R2, [R1], #-1 TEQ R1, R0 BNE %BT10 ; now make top row a 'top' row LDR R0, [WsPtr, #TTXMapPtr] ; R0 -> top line dummy word LDR R1, [R0] ; R1 = dummy word BIC R1, R1, #MapBit_Bottom ; clear 'bottom' bit STR R1, [R0] ; and store back Pull PC ; ***************************************************************************** ; ; TTXSoftScrollDown - Scroll screen down by software in teletext mode ; TTXSoftScrollDown ROUT ; first scroll map down LDR R0, [WsPtr, #RowLength] ; save real RowLength LDR R1, [WsPtr, #TWTRow] ; top row LDR R3, [WsPtr, #TWBRow] ; bottom row LDR R2, [WsPtr, #TTXLineStartsPtr] LDR R2, [R2, R3, LSL #2] ; R2 -> dummy char bottom row ADD R2, R2, #4 ; R2 -> 0th char bottom row LDR R4, [WsPtr, #TWLCol] LDR R5, [WsPtr, #TWRCol] Push "R0-R6,R14" ; and save CursorFlags ADD R2, R2, R4, LSL #2 ; R2 -> bottom left char SUB R5, R5, R4 ADD R5, R5, #1 ; R5 = no. of chars wide MOV R5, R5, LSL #2 ; R5 = no. of bytes / line SUB R6, R3, R1 ADD R6, R6, #1 ; R6 = no. of 'pixel' rows LDR R7, [WsPtr, #ScrRCol] ADD R7, R7, #2 MOV R7, R7, LSL #2 ; R7 = line length STR R7, [WsPtr, #RowLength] ; pretend row length MOV R0, #1 ; pretend rowmult =1 BL SoftScrollDown2 Pull "R0-R6" STR R0, [WsPtr, #RowLength] ; restore RowLength ; now R1=top row, R2 -> char 0 on row R3, R3=bottom row, R4=left, R5=right ; now clear top row LDR R7, [WsPtr, #TTXLineStartsPtr] LDR R7, [R7, R1, LSL #2] ; R7 -> dummy word(top) ADD R8, R7, R5, LSL #2 ; R8 -> char before top rt ADD R7, R7, R4, LSL #2 ; R7 -> char before top left MOV R0, #32 30 STRB R0, [R7, #4]! ; zap to space CMP R7, R8 ; if <= char before bottom rt BLS %BT30 ; then loop SUB R9, R8, R5, LSL #2 ; R9 -> dummy word(top) ADD R9, R9, #4 ; R9 -> map(0,top) MOV R2, R9 B CountAndRescan ; count doubles and rescan ; from top of window ; ***************************************************************************** ; ; TTXScrollLeft - Scroll left (by software) in Teletext mode ; ; in: R0 bit0=0 => scroll window ; 1 => scroll screen ; TTXScrollLeft ROUT Push R14 BL TTXSideScroll1 MOV R5, R0 ; R5 = left = column to check ; for double height chars BL TTXSideScroll2 ; do second part BL ScrollLeft2 ; now store spaces in right hand column Pull "R0-R3, R6, R9" ADD R4, R9, R2, LSL #2 ; R4 -> map(right,top) TTXSideScroll3 MOV R7, R3 ; R7 = current row MOV R8, #32 ; poke spaces LDR R10, [WsPtr, #ScrRCol] ADD R10, R10, #2 20 STRB R8, [R4], R10, LSL #2 ; store space and move down ADD R7, R7, #1 ; next row CMP R7, R1 ; if row <= bottom BLS %BT20 ; then loop ; now rescan from top of window/screen ADD R10, R1, #1 ; R10 = bottom+1 MOV R11, R3 ; R11 = top ADD R7, R9, R0, LSL #2 ; R7 -> map(left,top) ADD R5, R9, R2, LSL #2 ; R5 -> map(right,top) MOV R1, R3 ; R1 = top B TTXScanZap2 ; ***************************************************************************** ; ; TTXScrollRight - Scroll right (by software) in Teletext mode ; ; in: R0 bit0=0 => scroll window ; 1 => scroll screen ; TTXScrollRight ROUT Push R14 BL TTXSideScroll1 MOV R5, R2 ; R5 = right = column to check ; for double height chars BL TTXSideScroll2 BL ScrollRight2 ; now store spaces in left hand column Pull "R0-R3, R6, R9" ADD R4, R9, R0, LSL #2 ; R4 -> map(left,top) B TTXSideScroll3 ; ***************************************************************************** ; ; TTXSideScroll1 - Do first part of sideways scroll ; TTXSideScroll1 ROUT MOVS R0, R0, LSR #1 ; C=0 => scroll window ADDCC R0, WsPtr, #TWLCol ; R0 = left, R1 = bottom LDMCCIA R0, {R0-R3} ; R2 = right, R3 = top ; C=1 => scroll screen MOVCS R0, #0 ; left LDRCS R1, [WsPtr, #ScrBRow] ; bottom LDRCS R2, [WsPtr, #ScrRCol] ; right MOVCS R3, #0 ; top MOV PC, R14 ; ***************************************************************************** ; ; TTXSideScroll2 - Do second part of sideways scroll ; ; in: R5 = left or right hand column for left or right scroll respectively ; TTXSideScroll2 ROUT ; first check char R5 on each line and decrement double count if a double LDR R4, [WsPtr, #TTXLineStartsPtr] LDR R4, [R4, R3, LSL #2] ; R4 -> map(dummy,top) ADD R9, R4, #4 ; R9 -> map(0,top) ADD R4, R9, R5, LSL #2 ; R4 -> map(left or right,top) Push "R9" LDR R9, [WsPtr, #ScrRCol] ADD R9, R9, #2 LDR R5, [WsPtr, #TTXDoubleCountsPtr] MOV R7, R3 ; R7 = current row 10 LDR R8, [R4], R9, LSL #2 ; get char+attr AND R8, R8, #&7F TEQ R8, #TTX_DoubleHeight ; test if double height char LDREQB R8, [R5, R7] ; if so then load double count SUBEQ R8, R8, #1 ; decrement it STREQB R8, [R5, R7] ; and store back ADD R7, R7, #1 ; next row CMP R7, R1 ; if row <= bottom BLS %BT10 ; then loop ; now scroll map MOV R7, R9, LSL #2 ; linelength LDR R9, [sp] Push "R0-R3, R6" SUB R5, R2, R0 ; R5 = right-left ADD R5, R5, #1 ; R5 = right-left+1 MOV R5, R5, LSL #2 ; R5 = (right-left+1)*4 ADD R2, R9, R0, LSL #2 ; R2 -> map(left,top) SUB R6, R1, R3 ; R6 = bottom-top ADD R6, R6, #1 ; R6 = bottom-top+1 MOV R9, #4 ; no. of bytes to scroll by MOV PC, R14 ; ***************************************************************************** ; ; UpdateHeldBits - change the held graphic bits of R0 if necessary ; TTXPaintChar used to have this functionality ; UpdateHeldBits ROUT TST R0, #&60 :OR: MapBit_Hold ; if a control code and not holding, BICEQ R0, R0, #MapBit_HeldMask ; clear mask MOVEQ PC, R14 TST R0, #MapBit_Graph TSTNE R0, #&20 ; if not a graphic character, MOVEQ PC, R14 ; preserve the bits that were copied from the previous character BIC R0, R0, #MapBit_HeldMask ; else copy the character to the held graphic bits ORR R0, R0, R0, LSL #MapHeldShift TST R0, #MapBit_Separated BICEQ R0, R0, #MapBit_HeldSeparated ORRNE R0, R0, #MapBit_HeldSeparated MOV PC, R14 ; ***************************************************************************** ; ; TTXPaintChar - Paint char according to attributes ; ; in: R0 = character + attributes word ; R2 -> screen (for the time being) ; ; out: R3, R12 corrupt TTXPaintChar ROUT Entry "R1,R4-R11" VDWS WsPtr ; for now ; first set up the colours ADD R1, WsPtr, #TForeCol LDMIA R1, {R1, R3} ; R1 = TForeCol; R3 = TBackCol MOV R4, #&0F LDR R14, [WsPtr, #TTXFlags] BIC R5, R0, R14 ; apply BIC masks EOR R14, R5, R14, LSL #8 ; apply EOR masks AND R5, R4, R14, LSR #MapForeShift ; R5 = new foregd colour AND R6, R4, R14, LSR #MapBackShift ; R6 = new backgd colour TEQ R1, R5 ; if foregd different TEQEQ R3, R6 ; or backgd different BLNE TTXUpdateColours ; then update colour table [ HiResTTX ADRL R1, TTXHardFont-32*40 ; R1 -> base for font | ADRL R1, TTXHardFont-32*10 ; R1 -> base for font ] MOVS R3, R0, LSL #26 ; C := bit6, N := bit5 AND R3, R0, #&7F ; R3 = char BMI %FT10 ; [&20-&3F or &60-&7F] BCS %FT20 ; [&40-&5F (definitely Alpha)] ; control code, so display as space or held graphic TST R0, #MapBit_Hold ; zero if not holding MOVEQ R3, #&20 ; pretend to be space BEQ %FT20 ; [display as space] ; next instruction assumes no valid bits above held graphic bits MOV R3, R0, LSR #MapHeldShift ; R3 = char to display B %FT30 ; [display as held graphic] ; char in range &20-&3F or &60-&7F, so check for alpha/graphics 10 TST R0, #MapBit_Graph ; in graphics mode BEQ %FT20 ; [no, so definitely Alpha] TST R0, #MapBit_Separated ; separated graphics ? BICEQ R3, R3, #&20 ; no, then make &00-&1F,&40-&5F 30 ADD R1, WsPtr, #TTXSoftFonts [ HiResTTX TST R3, #&5F ; if a space ADREQL R1, TTXHardFont ; then just use the hard font, for speed BLNE ComputeGraphic ; else generate the bitmap B %FT40 20 ADD R1, R1, R3, LSL #5 ; add 32*char ADD R1, R1, R3, LSL #3 ; add 8*char 40 | 20 ADD R1, R1, R3, LSL #3 ; add 8*char ADD R1, R1, R3, LSL #1 ; add 2*char ] TST R0, #MapBit_Conceal ; concealing ? LDRNE R14, [WsPtr, #TTXFlags] TSTNE R14, #TTXFlag_Conceal ; and reveal is off? ADRNEL R1, TTXHardFont ; yes, then display as space [ :LNOT: HiResTTX ; now load font bytes ; 0..3 into tophalf ; 4..7 into bottomhalf ; 8..9 into R10 (top 2 bytes) TST R1, #2 ; starting on a word bdy ? SUBNE R1, R1, #2 ; if not, move back LDMIA R1, {tophalf, bottomhalf, R10} ; yes, so load all 3 up MOVEQ R10, R10, LSL #16 MOVNE tophalf, tophalf, LSR #16 ORRNE tophalf, tophalf, bottomhalf, LSL #16 MOVNE bottomhalf, bottomhalf, LSR #16 ORRNE bottomhalf, bottomhalf, R10, LSL #16 TST R0, #(MapBit_Bottom :OR: MapBit_Double) BLNE PrintDoubleHeight LDR bigfont, [WsPtr, #TextExpandArea] MOV mask, #&FF000000 LDR linelen, [WsPtr, #LineLength] Push "R0, screen" MOV R0, #0 ; indicate 10 rows BL Wrch4bitTTX ; do 1st bank LDMFD R13, {R0, screen} ; restore char + scr. addr LDR byte, [WsPtr, #ScreenSize] ADD screen, screen, byte, LSR #1 ; point to 2nd bank TST R0, #MapBit_Flash MOVNE mask, #0 ; flash => 2nd bank is space MOV R0, #0 BL Wrch4bitTTX Pull "R0, screen" EXIT | ; here we do the two screen banks in an outer loop and have a ; 5-stage inner loop each time plotting 4 rows (1/5th of the character) TST R0, #MapBit_Bottom ; for bottom-half characters ADDNE R1, R1, #2*10 ; start half-way through the character LDR bigfont, [WsPtr, #TextExpandArea] MOV mask, #&FF000000 LDR linelen, [WsPtr, #LineLength] LDR byte, [WsPtr, #CharWidth] SUB linelen, linelen, byte, LSR #1 ; adjust line offset to account for performing two screen writes per row Push "R1, screen" BL WrchHiResTTX ; do 1st bank LDMFD R13, {R1, screen} ; restore pointers to character and screen address LDR byte, [WsPtr, #ScreenSize] ADD screen, screen, byte, LSR #1 ; point to 2nd bank TST R0, #MapBit_Flash MOVNE mask, #0 ; flash => 2nd bank is space BL WrchHiResTTX ; do 2nd bank Pull "R1, screen" EXIT ; ***************************************************************************** ; ; WrchHiResTTX - Write a high-res teletext char to screen ; ; in: R0 = character + attributes word ; R1 -> character definition ; screen -> screen ; bigfont -> font definition ; mask = &FF000000 for normal, &0 for blank ; linelen = LineLength-(CharWidth/2) ; ; out: tophalf, bottomhalf, byte, scrbyte, scrbyte2, R7 corrupt ; WrchHiResTTX ROUT Entry LDR R7, [WsPtr, #Log2BPP] ADR R14, WrchHiResTTXTab - 8 LDR R14, [R14, R7, LSL #2] MOV R7, #4 ; do each plot in 5 stages; R7 holds stage number 01 TST R0, #MapBit_Double LDMEQIA R1!, {tophalf, bottomhalf} ; single height characters, load 4 rows LDRNE tophalf, [R1], #4 ; double height characters, load 2 rows MOVNE bottomhalf, tophalf, LSR #16 ; and double up ORRNE bottomhalf, bottomhalf, bottomhalf, LSL #16 MOVNE tophalf, tophalf, LSL #16 ORRNE tophalf, tophalf, tophalf, LSR #16 AND byte, R0, #(MapBit_Double :OR: MapBit_Bottom) ; byte is used here as a scratch register TEQ byte, #MapBit_Bottom ; if single height on line below top-half double height, MOVEQ tophalf, #0 ; make it invisible MOVEQ bottomhalf, #0 MOV PC, R14 ; call routine WrchHiResTTX8 AND byte, mask, tophalf, LSL #16 ADD byte, bigfont, byte, LSR #21 LDMIA byte, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} AND byte, mask, tophalf, LSL #24 ADD byte, bigfont, byte, LSR #21 LDMIA byte, {scrbyte, scrbyte2} STMIA screen, {scrbyte, scrbyte2} ADD screen, screen, linelen AND byte, mask, tophalf ADD byte, bigfont, byte, LSR #21 LDMIA byte, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} AND byte, mask, tophalf, LSL #8 ADD byte, bigfont, byte, LSR #21 LDMIA byte, {scrbyte, scrbyte2} STMIA screen, {scrbyte, scrbyte2} ADD screen, screen, linelen AND byte, mask, bottomhalf, LSL #16 ADD byte, bigfont, byte, LSR #21 LDMIA byte, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} AND byte, mask, bottomhalf, LSL #24 ADD byte, bigfont, byte, LSR #21 LDMIA byte, {scrbyte, scrbyte2} STMIA screen, {scrbyte, scrbyte2} ADD screen, screen, linelen AND byte, mask, bottomhalf ADD byte, bigfont, byte, LSR #21 LDMIA byte, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} AND byte, mask, bottomhalf, LSL #8 ADD byte, bigfont, byte, LSR #21 LDMIA byte, {scrbyte, scrbyte2} STMIA screen, {scrbyte, scrbyte2} ADD screen, screen, linelen SUBS R7, R7, #1 BPL %BT01 EXIT WrchHiResTTX4 AND byte, mask, tophalf, LSL #16 LDR scrbyte, [bigfont, byte, LSR #22] STR scrbyte, [screen], #4 AND byte, mask, tophalf, LSL #24 LDR scrbyte, [bigfont, byte, LSR #22] STR scrbyte, [screen], linelen AND byte, mask, tophalf LDR scrbyte, [bigfont, byte, LSR #22] STR scrbyte, [screen], #4 AND byte, mask, tophalf, LSL #8 LDR scrbyte, [bigfont, byte, LSR #22] STR scrbyte, [screen], linelen AND byte, mask, bottomhalf, LSL #16 LDR scrbyte, [bigfont, byte, LSR #22] STR scrbyte, [screen], #4 AND byte, mask, bottomhalf, LSL #24 LDR scrbyte, [bigfont, byte, LSR #22] STR scrbyte, [screen], linelen AND byte, mask, bottomhalf LDR scrbyte, [bigfont, byte, LSR #22] STR scrbyte, [screen], #4 AND byte, mask, bottomhalf, LSL #8 LDR scrbyte, [bigfont, byte, LSR #22] STR scrbyte, [screen], linelen SUBS R7, R7, #1 BPL %BT01 EXIT WrchHiResTTX16 SUB linelen, linelen, #16 AND byte, mask, tophalf, LSL #16 ADD byte, bigfont, byte, LSR #20 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} AND byte, mask, tophalf, LSL #24 ADD byte, bigfont, byte, LSR #20 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} ADD screen, screen, linelen AND byte, mask, tophalf ADD byte, bigfont, byte, LSR #20 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} AND byte, mask, tophalf, LSL #8 ADD byte, bigfont, byte, LSR #20 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} ADD screen, screen, linelen AND byte, mask, bottomhalf, LSL #16 ADD byte, bigfont, byte, LSR #20 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} AND byte, mask, bottomhalf, LSL #24 ADD byte, bigfont, byte, LSR #20 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} ADD screen, screen, linelen AND byte, mask, bottomhalf ADD byte, bigfont, byte, LSR #20 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} AND byte, mask, bottomhalf, LSL #8 ADD byte, bigfont, byte, LSR #20 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} ADD screen, screen, linelen SUBS R7, R7, #1 ADD linelen, linelen, #16 BPL %BT01 EXIT WrchHiResTTX32 SUB linelen, linelen, #32 AND byte, mask, tophalf, LSL #16 ADD byte, bigfont, byte, LSR #19 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} AND byte, mask, tophalf, LSL #24 ADD byte, bigfont, byte, LSR #19 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} ADD screen, screen, linelen AND byte, mask, tophalf ADD byte, bigfont, byte, LSR #19 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} AND byte, mask, tophalf, LSL #8 ADD byte, bigfont, byte, LSR #19 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} ADD screen, screen, linelen AND byte, mask, bottomhalf, LSL #16 ADD byte, bigfont, byte, LSR #19 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} AND byte, mask, bottomhalf, LSL #24 ADD byte, bigfont, byte, LSR #19 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} ADD screen, screen, linelen AND byte, mask, bottomhalf ADD byte, bigfont, byte, LSR #19 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} AND byte, mask, bottomhalf, LSL #8 ADD byte, bigfont, byte, LSR #19 LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} LDMIA byte!, {scrbyte, scrbyte2} STMIA screen!, {scrbyte, scrbyte2} ADD screen, screen, linelen SUBS R7, R7, #1 ADD linelen, linelen, #32 BPL %BT01 EXIT WrchHiResTTXTab & WrchHiResTTX4 & WrchHiResTTX8 & WrchHiResTTX16 & WrchHiResTTX32 ] ; ***************************************************************************** LTORG ; ***************************************************************************** ; ; DoPreControl - Process 'at' action of control char ; DoPostControl - Process 'after' action of control char ; ; in: R0 = new char + attributes of current previous char ; R1 = new char AND &7F ; (0 <= R1 <= 31) ; R9 = double height char counter ; ; out: R0 = updated char + attributes ; R3 = corrupt ; R9 = updated ; DoPreControl ROUT ADD PC, PC, R1, LSL #3 DoPostControl ROUT ADD PC, PC, R1, LSL #3 MOV PC, R14 ; &00 Pre B DoAlphaBlack ; &00 Post MOV PC, R14 ; &01 Pre B DoAlphaColour ; &01 Post MOV PC, R14 ; &02 Pre B DoAlphaColour ; &02 Post MOV PC, R14 ; &03 Pre B DoAlphaColour ; &03 Post MOV PC, R14 ; &04 Pre B DoAlphaColour ; &04 Post MOV PC, R14 ; &05 Pre B DoAlphaColour ; &05 Post MOV PC, R14 ; &06 Pre B DoAlphaColour ; &06 Post MOV PC, R14 ; &07 Pre B DoAlphaColour ; &07 Post MOV PC, R14 ; &08 Pre B DoFlash ; &08 Post BIC R0, R0, #MapBit_Flash ; &09 Pre ; clear flash mode MOV PC, R14 ; &09 Post B DoPreEndBox ; &0A Pre B DoPostEndBox ; &0A Post B DoPreStartBox ; &0B Pre B DoPostStartBox ; &0B Post B DoSingleHeight ; &0C Pre MOV PC, R14 ; &0C Post B DoDoubleHeight ; &0D Pre MOV PC, R14 ; &0D Post MOV PC, R14 ; &0E Pre MOV PC, R14 ; &0E Post MOV PC, R14 ; &0F Pre MOV PC, R14 ; &0F Post MOV PC, R14 ; &10 Pre B DoGraphBlack ; &10 Post MOV PC, R14 ; &11 Pre B DoGraphColour ; &11 Post MOV PC, R14 ; &12 Pre B DoGraphColour ; &12 Post MOV PC, R14 ; &13 Pre B DoGraphColour ; &13 Post MOV PC, R14 ; &14 Pre B DoGraphColour ; &14 Post MOV PC, R14 ; &15 Pre B DoGraphColour ; &15 Post MOV PC, R14 ; &16 Pre B DoGraphColour ; &16 Post MOV PC, R14 ; &17 Pre B DoGraphColour ; &17 Post ORR R0, R0, #MapBit_Conceal ; &18 Pre ; set conceal mode MOV PC, R14 ; &18 Post MOV PC, R14 ; &19 Pre BIC R0, R0, #MapBit_Separated ; &19 Post ; clear separated MOV PC, R14 ; &1A Pre ORR R0, R0, #MapBit_Separated ; &1A Post ; set separated MOV PC, R14 ; &1B Pre MOV PC, R14 ; &1B Post BIC R0, R0, #MapBit_BackMask ; &1C Pre ; clear backgd colour MOV PC, R14 ; &1C Post B DoNewBackgd ; &1D Pre MOV PC, R14 ; &1D Post ORR R0, R0, #MapBit_Hold ; &1E Pre ; set hold graph mode MOV PC, R14 ; &1E Post MOV PC, R14 ; &1F Pre BIC R0, R0, #MapBit_Hold ; &1F Post ; clear hold graph mode MOV PC, R14 ; ***************************************************************************** DoAlphaBlack LDR R3, [WsPtr, #TTXFlags] TST R3, #TTXFlag_BlackEnable ; unless enabled, MOVEQ PC, R14 ; do nothing ; drop through... DoAlphaColour BIC R0, R0, #MapBit_HeldMask ; clear held graphic BIC R0, R0, #(MapBit_ForeMask :OR: MapBit_Conceal) ; clear colour + conceal ORR R0, R0, R1, LSL #MapForeShift ; put in new colour BIC R0, R0, #MapBit_Graph ; set alpha mode MOV PC, R14 DoGraphBlack LDR R3, [WsPtr, #TTXFlags] TST R3, #TTXFlag_BlackEnable ; unless enabled, MOVEQ PC, R14 ; do nothing ; drop through... DoGraphColour BIC R0, R0, #(MapBit_ForeMask :OR: MapBit_Conceal) ; clear colour + conceal AND R3, R1, #&07 ; ensure only colour bits ORR R0, R0, R3, LSL #MapForeShift ; put in new colour ORR R0, R0, #MapBit_Graph ; set graph mode MOV PC, R14 DoFlash ORR R0, R0, #MapBit_Flash ; set flash mode MOV PC, R14 DoNewBackgd AND R3, R0, #MapBit_ForeMask ; R5 = fore colour BIC R0, R0, #MapBit_BackMask ; clear old backgd ORR R0, R0, R3, LSL #(MapBackShift-MapForeShift) ; new backgd MOV PC, R14 DoDoubleHeight TST R0, #MapBit_Double ; if currently single height BICEQ R0, R0, #MapBit_HeldMask ; then cancel held graphic ORR R0, R0, #MapBit_Double ; set double height mode ADD R9, R9, #1 ; one more double char MOV PC, R14 DoSingleHeight TST R0, #MapBit_Double ; if currently double height BICNE R0, R0, #MapBit_HeldMask ; then cancel held graphic BIC R0, R0, #MapBit_Double ; set single height mode MOV PC, R14 DoPreStartBox TST R0, #MapBit_PendingStart ; if prev char was start box ORRNE R0, R0, #MapBits_Boxed ; then start boxed area MOV PC, R14 DoPostStartBox ORR R0, R0, #MapBit_PendingStart ; "Previous char is Start Box" MOV PC, R14 DoPreEndBox TST R0, #MapBit_PendingEnd ; if prev char was end box BICNE R0, R0, #MapBits_Boxed ; then end boxed area MOV PC, R14 DoPostEndBox ORR R0, R0, #MapBit_PendingEnd ; "Previous char is End Box" MOV PC, R14 ; ***************************************************************************** TTXHardFont [ HiResTTX DCW &0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000 ; space DCW &0000,&0000,&0300,&0300,&0300,&0300,&0300,&0300,&0300,&0300,&0300,&0300,&0000,&0000,&0300,&0300,&0000,&0000,&0000,&0000 ; ! DCW &0000,&0000,&0C60,&0C60,&0C60,&0C60,&0C60,&0C60,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000 ; " DCW &0000,&0000,&03F0,&07F8,&0E1C,&0C0C,&0C00,&0C00,&3F80,&3F80,&0C00,&0C00,&0C00,&0C00,&3FFC,&3FFC,&0000,&0000,&0000,&0000 ; £ DCW &0000,&0000,&0FF0,&1FF8,&399C,&318C,&3180,&3980,&1FF0,&0FF8,&019C,&018C,&318C,&399C,&1FF8,&0FF0,&0000,&0000,&0000,&0000 ; $ DCW &0000,&0000,&3C00,&3C0C,&3C1C,&3C38,&0070,&00E0,&01C0,&0380,&0700,&0E00,&1C3C,&383C,&303C,&003C,&0000,&0000,&0000,&0000 ; % DCW &0000,&0000,&0E00,&1F00,&3B80,&3180,&3380,&3F00,&1E00,&1F00,&3F8C,&31DC,&30F8,&3878,&1FFC,&0FCC,&0000,&0000,&0000,&0000 ; & DCW &0000,&0000,&0180,&0180,&0180,&0180,&0180,&0180,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000 ; ' DCW &0000,&0000,&0060,&00E0,&01C0,&0380,&0700,&0600,&0600,&0600,&0600,&0700,&0380,&01C0,&00E0,&0060,&0000,&0000,&0000,&0000 ; ( DCW &0000,&0000,&0600,&0700,&0380,&01C0,&00E0,&0060,&0060,&0060,&0060,&00E0,&01C0,&0380,&0700,&0600,&0000,&0000,&0000,&0000 ; ) DCW &0000,&0000,&0180,&318C,&399C,&1DB8,&0FF0,&07E0,&03C0,&03C0,&07E0,&0FF0,&1DB8,&399C,&318C,&0180,&0000,&0000,&0000,&0000 ; * DCW &0000,&0000,&0000,&0000,&0180,&0180,&0180,&0180,&3FFC,&3FFC,&0180,&0180,&0180,&0180,&0000,&0000,&0000,&0000,&0000,&0000 ; + DCW &0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0180,&0180,&0180,&0180,&0380,&0300,&0000,&0000 ; , DCW &0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0FF0,&0FF0,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000 ; - DCW &0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0180,&0180,&0000,&0000,&0000,&0000 ; . DCW &0000,&0000,&0000,&0018,&0038,&0070,&00E0,&01C0,&0380,&0700,&0E00,&1C00,&1800,&0000,&0000,&0000,&0000,&0000,&0000,&0000 ; / DCW &0000,&0000,&03C0,&07E0,&0E70,&1C38,&381C,&300C,&300C,&300C,&300C,&381C,&1C38,&0E70,&07E0,&03C0,&0000,&0000,&0000,&0000 ; 0 DCW &0000,&0000,&0180,&0180,&0F80,&0F80,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0FF0,&0FF0,&0000,&0000,&0000,&0000 ; 1 DCW &0000,&0000,&0FF0,&1FF8,&381C,&300C,&000C,&001C,&07F8,&0FF0,&1C00,&3800,&3000,&3000,&3FFC,&3FFC,&0000,&0000,&0000,&0000 ; 2 DCW &0000,&0000,&3FFC,&3FFC,&001C,&0038,&0070,&00E0,&01F8,&01FC,&000C,&000C,&300C,&381C,&1FF8,&0FF0,&0000,&0000,&0000,&0000 ; 3 DCW &0000,&0000,&0070,&00F0,&01F0,&03B0,&0730,&0E30,&1C30,&3830,&3FFC,&3FFC,&0030,&0030,&0030,&0030,&0000,&0000,&0000,&0000 ; 4 DCW &0000,&0000,&3FFC,&3FFC,&3000,&3000,&3FF0,&3FF8,&001C,&000C,&000C,&000C,&300C,&381C,&1FF8,&0FF0,&0000,&0000,&0000,&0000 ; 5 DCW &0000,&0000,&01F0,&07F0,&0F00,&1C00,&3800,&3000,&3FF0,&3FF8,&301C,&300C,&300C,&381C,&1FF8,&0FF0,&0000,&0000,&0000,&0000 ; 6 DCW &0000,&0000,&3FFC,&3FFC,&000C,&001C,&0038,&0070,&00E0,&01C0,&0380,&0700,&0600,&0600,&0600,&0600,&0000,&0000,&0000,&0000 ; 7 DCW &0000,&0000,&0FF0,&1FF8,&381C,&300C,&300C,&381C,&1FF8,&1FF8,&381C,&300C,&300C,&381C,&1FF8,&0FF0,&0000,&0000,&0000,&0000 ; 8 DCW &0000,&0000,&0FF0,&1FF8,&381C,&300C,&300C,&380C,&1FFC,&0FFC,&000C,&001C,&0038,&00F0,&0FE0,&0F80,&0000,&0000,&0000,&0000 ; 9 DCW &0000,&0000,&0000,&0000,&0000,&0000,&0180,&0180,&0000,&0000,&0000,&0000,&0000,&0000,&0180,&0180,&0000,&0000,&0000,&0000 ; : DCW &0000,&0000,&0000,&0000,&0000,&0000,&0180,&0180,&0000,&0000,&0000,&0000,&0180,&0180,&0180,&0180,&0380,&0300,&0000,&0000 ; ; DCW &0000,&0000,&0060,&00E0,&01C0,&0380,&0700,&0E00,&1C00,&1C00,&0E00,&0700,&0380,&01C0,&00E0,&0060,&0000,&0000,&0000,&0000 ; < DCW &0000,&0000,&0000,&0000,&0000,&0000,&3FFC,&3FFC,&0000,&0000,&3FFC,&3FFC,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000 ; = DCW &0000,&0000,&0600,&0700,&0380,&01C0,&00E0,&0070,&0038,&0038,&0070,&00E0,&01C0,&0380,&0700,&0600,&0000,&0000,&0000,&0000 ; > DCW &0000,&0000,&0FE0,&1FF0,&3838,&3018,&0038,&0070,&00E0,&01C0,&0180,&0180,&0000,&0000,&0180,&0180,&0000,&0000,&0000,&0000 ; ? DCW &0000,&0000,&0FF0,&1FF8,&381C,&300C,&31FC,&31FC,&318C,&318C,&31FC,&31FC,&3000,&3800,&1FF0,&0FF0,&0000,&0000,&0000,&0000 ; @ DCW &0000,&0000,&0180,&03C0,&07E0,&0E70,&1C38,&381C,&300C,&300C,&3FFC,&3FFC,&300C,&300C,&300C,&300C,&0000,&0000,&0000,&0000 ; A DCW &0000,&0000,&3FF0,&3FF8,&301C,&300C,&300C,&301C,&3FF8,&3FF8,&301C,&300C,&300C,&301C,&3FF8,&3FF0,&0000,&0000,&0000,&0000 ; B DCW &0000,&0000,&0FF0,&1FF8,&381C,&300C,&3000,&3000,&3000,&3000,&3000,&3000,&300C,&381C,&1FF8,&0FF0,&0000,&0000,&0000,&0000 ; C DCW &0000,&0000,&3FF0,&3FF8,&301C,&300C,&300C,&300C,&300C,&300C,&300C,&300C,&300C,&301C,&3FF8,&3FF0,&0000,&0000,&0000,&0000 ; D DCW &0000,&0000,&3FFC,&3FFC,&3000,&3000,&3000,&3000,&3FF0,&3FF0,&3000,&3000,&3000,&3000,&3FFC,&3FFC,&0000,&0000,&0000,&0000 ; E DCW &0000,&0000,&3FFC,&3FFC,&3000,&3000,&3000,&3000,&3FF0,&3FF0,&3000,&3000,&3000,&3000,&3000,&3000,&0000,&0000,&0000,&0000 ; F DCW &0000,&0000,&0FF0,&1FF8,&381C,&300C,&3000,&3000,&3000,&3000,&303C,&303C,&300C,&380C,&1FFC,&0FFC,&0000,&0000,&0000,&0000 ; G DCW &0000,&0000,&300C,&300C,&300C,&300C,&300C,&300C,&3FFC,&3FFC,&300C,&300C,&300C,&300C,&300C,&300C,&0000,&0000,&0000,&0000 ; H DCW &0000,&0000,&0FF0,&0FF0,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0FF0,&0FF0,&0000,&0000,&0000,&0000 ; I DCW &0000,&0000,&000C,&000C,&000C,&000C,&000C,&000C,&000C,&000C,&000C,&000C,&300C,&381C,&1FF8,&0FF0,&0000,&0000,&0000,&0000 ; J DCW &0000,&0000,&1818,&1838,&1870,&18E0,&19C0,&1B80,&1F00,&1F00,&1B80,&19C0,&18E0,&1870,&1838,&1818,&0000,&0000,&0000,&0000 ; K DCW &0000,&0000,&3000,&3000,&3000,&3000,&3000,&3000,&3000,&3000,&3000,&3000,&3000,&3000,&3FFC,&3FFC,&0000,&0000,&0000,&0000 ; L DCW &0000,&0000,&300C,&300C,&381C,&3C3C,&3E7C,&37EC,&33CC,&318C,&300C,&300C,&300C,&300C,&300C,&300C,&0000,&0000,&0000,&0000 ; M DCW &0000,&0000,&300C,&300C,&380C,&3C0C,&3E0C,&370C,&338C,&31CC,&30EC,&307C,&303C,&301C,&300C,&300C,&0000,&0000,&0000,&0000 ; N DCW &0000,&0000,&0FF0,&1FF8,&381C,&300C,&300C,&300C,&300C,&300C,&300C,&300C,&300C,&381C,&1FF8,&0FF0,&0000,&0000,&0000,&0000 ; O DCW &0000,&0000,&3FF0,&3FF8,&301C,&300C,&300C,&301C,&3FF8,&3FF0,&3000,&3000,&3000,&3000,&3000,&3000,&0000,&0000,&0000,&0000 ; P DCW &0000,&0000,&0FF0,&1FF8,&381C,&300C,&300C,&300C,&300C,&300C,&30CC,&30EC,&3078,&3838,&1FFC,&0FCC,&0000,&0000,&0000,&0000 ; Q DCW &0000,&0000,&3FF0,&3FF8,&301C,&300C,&300C,&301C,&3FF8,&3FF0,&31C0,&30E0,&3070,&3038,&301C,&300C,&0000,&0000,&0000,&0000 ; R DCW &0000,&0000,&0FF0,&1FF8,&381C,&300C,&3000,&3800,&1FF0,&0FF8,&001C,&000C,&300C,&381C,&1FF8,&0FF0,&0000,&0000,&0000,&0000 ; S DCW &0000,&0000,&3FFC,&3FFC,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0000,&0000,&0000,&0000 ; T DCW &0000,&0000,&300C,&300C,&300C,&300C,&300C,&300C,&300C,&300C,&300C,&300C,&300C,&381C,&1FF8,&0FF0,&0000,&0000,&0000,&0000 ; U DCW &0000,&0000,&300C,&300C,&300C,&300C,&381C,&1818,&1C38,&0C30,&0E70,&07E0,&03C0,&03C0,&0180,&0180,&0000,&0000,&0000,&0000 ; V DCW &0000,&0000,&300C,&300C,&300C,&300C,&300C,&300C,&318C,&318C,&318C,&318C,&318C,&3FFC,&1FF8,&0E70,&0000,&0000,&0000,&0000 ; W DCW &0000,&0000,&300C,&300C,&381C,&1C38,&0E70,&07E0,&03C0,&03C0,&07E0,&0E70,&1C38,&381C,&300C,&300C,&0000,&0000,&0000,&0000 ; X DCW &0000,&0000,&300C,&300C,&381C,&1C38,&0E70,&07E0,&03C0,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0000,&0000,&0000,&0000 ; Y DCW &0000,&0000,&3FFC,&3FFC,&001C,&0038,&0070,&00E0,&01C0,&0380,&0700,&0E00,&1C00,&3800,&3FFC,&3FFC,&0000,&0000,&0000,&0000 ; Z DCW &0000,&0000,&0000,&0000,&0300,&0700,&0E00,&1C00,&3FFC,&3FFC,&1C00,&0E00,&0700,&0300,&0000,&0000,&0000,&0000,&0000,&0000 ; ˆ DCW &0000,&0000,&3000,&3000,&3000,&3000,&3000,&3000,&3000,&3000,&31F0,&31F8,&000C,&000C,&0018,&0070,&00C0,&0180,&01FC,&01FC ; ½ DCW &0000,&0000,&0000,&0000,&00C0,&00E0,&0070,&0038,&3FFC,&3FFC,&0038,&0070,&00E0,&00C0,&0000,&0000,&0000,&0000,&0000,&0000 ; ‰ DCW &0000,&0000,&0000,&0000,&0180,&03C0,&07E0,&0FF0,&1DB8,&1998,&0180,&0180,&0180,&0180,&0000,&0000,&0000,&0000,&0000,&0000 ; ‹ DCW &0000,&0000,&0630,&0630,&0630,&0630,&1FFC,&1FFC,&0630,&0630,&1FFC,&1FFC,&0630,&0630,&0630,&0630,&0000,&0000,&0000,&0000 ; # DCW &0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&FFFF,&FFFF,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000,&0000 ; ˜ DCW &0000,&0000,&0000,&0000,&0000,&0000,&1FF0,&1FF8,&001C,&000C,&1FFC,&3FFC,&300C,&300C,&3FFC,&1FFC,&0000,&0000,&0000,&0000 ; a DCW &0000,&0000,&3000,&3000,&3000,&3000,&3FF0,&3FF8,&301C,&300C,&300C,&300C,&300C,&301C,&3FF8,&3FF0,&0000,&0000,&0000,&0000 ; b DCW &0000,&0000,&0000,&0000,&0000,&0000,&0FFC,&1FFC,&3800,&3000,&3000,&3000,&3000,&3800,&1FFC,&0FFC,&0000,&0000,&0000,&0000 ; c DCW &0000,&0000,&000C,&000C,&000C,&000C,&0FFC,&1FFC,&380C,&300C,&300C,&300C,&300C,&380C,&1FFC,&0FFC,&0000,&0000,&0000,&0000 ; d DCW &0000,&0000,&0000,&0000,&0000,&0000,&0FF0,&1FF8,&381C,&300C,&3FFC,&3FFC,&3000,&3800,&1FF8,&0FF8,&0000,&0000,&0000,&0000 ; e DCW &0000,&0000,&0030,&00F0,&01C0,&0180,&0180,&0180,&0FF0,&0FF0,&0180,&0180,&0180,&0180,&0180,&0180,&0000,&0000,&0000,&0000 ; f DCW &0000,&0000,&0000,&0000,&0000,&0000,&0FFC,&1FFC,&380C,&300C,&300C,&300C,&300C,&380C,&1FFC,&0FFC,&000C,&001C,&0FF8,&0FF0 ; g DCW &0000,&0000,&3000,&3000,&3000,&3000,&3FF0,&3FF8,&301C,&300C,&300C,&300C,&300C,&300C,&300C,&300C,&0000,&0000,&0000,&0000 ; h DCW &0000,&0000,&0180,&0180,&0000,&0000,&0F80,&0F80,&0180,&0180,&0180,&0180,&0180,&0180,&0FF0,&0FF0,&0000,&0000,&0000,&0000 ; i DCW &0000,&0000,&0180,&0180,&0000,&0000,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0380,&0F00,&0C00 ; j DCW &0000,&0000,&1800,&1800,&1800,&1800,&1818,&1838,&18F0,&1BC0,&1F80,&1F80,&19C0,&18F0,&1838,&1818,&0000,&0000,&0000,&0000 ; k DCW &0000,&0000,&0F80,&0F80,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0180,&0FF0,&0FF0,&0000,&0000,&0000,&0000 ; l DCW &0000,&0000,&0000,&0000,&0000,&0000,&3E30,&3FF8,&33FC,&318C,&318C,&318C,&318C,&318C,&318C,&318C,&0000,&0000,&0000,&0000 ; m DCW &0000,&0000,&0000,&0000,&0000,&0000,&3FF0,&3FF8,&301C,&300C,&300C,&300C,&300C,&300C,&300C,&300C,&0000,&0000,&0000,&0000 ; n DCW &0000,&0000,&0000,&0000,&0000,&0000,&0FF0,&1FF8,&381C,&300C,&300C,&300C,&300C,&381C,&1FF8,&0FF0,&0000,&0000,&0000,&0000 ; o DCW &0000,&0000,&0000,&0000,&0000,&0000,&3FF0,&3FF8,&301C,&300C,&300C,&300C,&300C,&301C,&3FF8,&3FF0,&3000,&3000,&3000,&3000 ; p DCW &0000,&0000,&0000,&0000,&0000,&0000,&0FFC,&1FFC,&380C,&300C,&300C,&300C,&300C,&380C,&1FFC,&0FFC,&000C,&000C,&000C,&000C ; q DCW &0000,&0000,&0000,&0000,&0000,&0000,&31FC,&33FC,&3E00,&3C00,&3000,&3000,&3000,&3000,&3000,&3000,&0000,&0000,&0000,&0000 ; r DCW &0000,&0000,&0000,&0000,&0000,&0000,&0FFC,&1FFC,&3000,&3000,&1FF0,&0FF8,&000C,&000C,&3FF8,&3FF0,&0000,&0000,&0000,&0000 ; s DCW &0000,&0000,&0180,&0180,&0180,&0180,&0FF0,&0FF0,&0180,&0180,&0180,&0180,&0180,&01C0,&00F0,&0030,&0000,&0000,&0000,&0000 ; t DCW &0000,&0000,&0000,&0000,&0000,&0000,&300C,&300C,&300C,&300C,&300C,&300C,&300C,&380C,&1FFC,&0FFC,&0000,&0000,&0000,&0000 ; u DCW &0000,&0000,&0000,&0000,&0000,&0000,&300C,&300C,&300C,&381C,&1818,&1C38,&0E70,&07E0,&03C0,&0180,&0000,&0000,&0000,&0000 ; v DCW &0000,&0000,&0000,&0000,&0000,&0000,&300C,&300C,&300C,&300C,&318C,&318C,&318C,&3FFC,&1FF8,&0E70,&0000,&0000,&0000,&0000 ; w DCW &0000,&0000,&0000,&0000,&0000,&0000,&300C,&381C,&1E78,&0FF0,&03C0,&03C0,&0FF0,&1E78,&381C,&300C,&0000,&0000,&0000,&0000 ; x DCW &0000,&0000,&0000,&0000,&0000,&0000,&300C,&300C,&300C,&300C,&300C,&300C,&300C,&380C,&1FFC,&0FFC,&000C,&001C,&0FF8,&0FF0 ; y DCW &0000,&0000,&0000,&0000,&0000,&0000,&3FFC,&3FFC,&0038,&00F0,&01E0,&0780,&0F00,&1C00,&3FFC,&3FFC,&0000,&0000,&0000,&0000 ; z DCW &0000,&0000,&1800,&1800,&1800,&1800,&1800,&1800,&1800,&1800,&1818,&1838,&00F8,&0198,&0318,&0318,&03F8,&03F8,&0018,&0018 ; ¼ DCW &0000,&0000,&0C60,&0C60,&0C60,&0C60,&0C60,&0C60,&0C60,&0C60,&0C60,&0C60,&0C60,&0C60,&0C60,&0C60,&0000,&0000,&0000,&0000 ; || DCW &0000,&0000,&3E00,&3F00,&0180,&0180,&3F00,&3F00,&0180,&0180,&3F0C,&3E1C,&007C,&00CC,&018C,&018C,&01FC,&01FC,&000C,&000C ; ¾ DCW &0000,&0000,&0000,&0000,&0180,&0180,&0000,&0000,&3FFC,&3FFC,&0000,&0000,&0180,&0180,&0000,&0000,&0000,&0000,&0000,&0000 ; ÷ DCW &0000,&0000,&3FFC,&3FFC,&3FFC,&3FFC,&3FFC,&3FFC,&3FFC,&3FFC,&3FFC,&3FFC,&3FFC,&3FFC,&3FFC,&3FFC,&0000,&0000,&0000,&0000 ; block | = &00,&00,&00,&00,&00,&00,&00,&00,&00,&00 ; space = &00,&08,&08,&08,&08,&08,&00,&08,&00,&00 ; ! = &00,&14,&14,&14,&00,&00,&00,&00,&00,&00 ; " = &00,&0C,&12,&10,&38,&10,&10,&3E,&00,&00 ; ` = &00,&1C,&2A,&28,&1C,&0A,&2A,&1C,&00,&00 ; $ = &00,&30,&32,&04,&08,&10,&26,&06,&00,&00 ; % = &00,&10,&28,&28,&10,&2A,&24,&1A,&00,&00 ; & = &00,&08,&08,&08,&00,&00,&00,&00,&00,&00 ; ' = &00,&04,&08,&10,&10,&10,&08,&04,&00,&00 ; ( = &00,&10,&08,&04,&04,&04,&08,&10,&00,&00 ; ) = &00,&08,&2A,&1C,&08,&1C,&2A,&08,&00,&00 ; * = &00,&00,&08,&08,&3E,&08,&08,&00,&00,&00 ; + = &00,&00,&00,&00,&00,&00,&08,&08,&10,&00 ; , = &00,&00,&00,&00,&1C,&00,&00,&00,&00,&00 ; - = &00,&00,&00,&00,&00,&00,&00,&08,&00,&00 ; . = &00,&00,&02,&04,&08,&10,&20,&00,&00,&00 ; / = &00,&08,&14,&22,&22,&22,&14,&08,&00,&00 ; 0 = &00,&08,&18,&08,&08,&08,&08,&1C,&00,&00 ; 1 = &00,&1C,&22,&02,&0C,&10,&20,&3E,&00,&00 ; 2 = &00,&3E,&02,&04,&0C,&02,&22,&1C,&00,&00 ; 3 = &00,&04,&0C,&14,&24,&3E,&04,&04,&00,&00 ; 4 = &00,&3E,&20,&3C,&02,&02,&22,&1C,&00,&00 ; 5 = &00,&0C,&10,&20,&3C,&22,&22,&1C,&00,&00 ; 6 = &00,&3E,&02,&04,&08,&10,&10,&10,&00,&00 ; 7 = &00,&1C,&22,&22,&1C,&22,&22,&1C,&00,&00 ; 8 = &00,&1C,&22,&22,&1E,&02,&04,&18,&00,&00 ; 9 = &00,&00,&00,&08,&00,&00,&08,&00,&00,&00 ; : = &00,&00,&00,&08,&00,&00,&08,&08,&10,&00 ; ; = &00,&04,&08,&10,&20,&10,&08,&04,&00,&00 ; < = &00,&00,&00,&3E,&00,&3E,&00,&00,&00,&00 ; = = &00,&10,&08,&04,&02,&04,&08,&10,&00,&00 ; > = &00,&1C,&22,&04,&08,&08,&00,&08,&00,&00 ; ? = &00,&1C,&22,&2E,&2A,&2E,&20,&1C,&00,&00 ; @ = &00,&08,&14,&22,&22,&3E,&22,&22,&00,&00 ; A = &00,&3C,&22,&22,&3C,&22,&22,&3C,&00,&00 ; B = &00,&1C,&22,&20,&20,&20,&22,&1C,&00,&00 ; C = &00,&3C,&22,&22,&22,&22,&22,&3C,&00,&00 ; D = &00,&3E,&20,&20,&3C,&20,&20,&3E,&00,&00 ; E = &00,&3E,&20,&20,&3C,&20,&20,&20,&00,&00 ; F = &00,&1C,&22,&20,&20,&26,&22,&1E,&00,&00 ; G = &00,&22,&22,&22,&3E,&22,&22,&22,&00,&00 ; H = &00,&1C,&08,&08,&08,&08,&08,&1C,&00,&00 ; I = &00,&02,&02,&02,&02,&02,&22,&1C,&00,&00 ; J = &00,&22,&24,&28,&30,&28,&24,&22,&00,&00 ; K = &00,&20,&20,&20,&20,&20,&20,&3E,&00,&00 ; L = &00,&22,&36,&2A,&22,&22,&22,&22,&00,&00 ; M = &00,&22,&22,&32,&2A,&26,&22,&22,&00,&00 ; N = &00,&1C,&22,&22,&22,&22,&22,&1C,&00,&00 ; O = &00,&3C,&22,&22,&3C,&20,&20,&20,&00,&00 ; P = &00,&1C,&22,&22,&22,&2A,&24,&1A,&00,&00 ; Q = &00,&3C,&22,&22,&3C,&28,&24,&22,&00,&00 ; R = &00,&1C,&22,&20,&1C,&02,&22,&1C,&00,&00 ; S = &00,&3E,&08,&08,&08,&08,&08,&08,&00,&00 ; T = &00,&22,&22,&22,&22,&22,&22,&1C,&00,&00 ; U = &00,&22,&22,&22,&14,&14,&08,&08,&00,&00 ; V = &00,&22,&22,&22,&2A,&2A,&2A,&14,&00,&00 ; W = &00,&22,&22,&14,&08,&14,&22,&22,&00,&00 ; X = &00,&22,&22,&14,&08,&08,&08,&08,&00,&00 ; Y = &00,&3E,&02,&04,&08,&10,&20,&3E,&00,&00 ; Z = &00,&00,&08,&10,&3E,&10,&08,&00,&00,&00 ; [ = &00,&20,&20,&20,&20,&2C,&02,&04,&08,&0E ; \  = &00,&00,&08,&04,&3E,&04,&08,&00,&00,&00 ; ] = &00,&00,&08,&1C,&2A,&08,&08,&00,&00,&00 ; ^ = &00,&14,&14,&3E,&14,&3E,&14,&14,&00,&00 ; # = &00,&00,&00,&00,&3E,&00,&00,&00,&00,&00 ; _ = &00,&00,&00,&1C,&02,&1E,&22,&1E,&00,&00 ; a = &00,&20,&20,&3C,&22,&22,&22,&3C,&00,&00 ; b = &00,&00,&00,&1E,&20,&20,&20,&1E,&00,&00 ; c = &00,&02,&02,&1E,&22,&22,&22,&1E,&00,&00 ; d = &00,&00,&00,&1C,&22,&3E,&20,&1C,&00,&00 ; e = &00,&04,&08,&08,&1C,&08,&08,&08,&00,&00 ; f = &00,&00,&00,&1E,&22,&22,&22,&1E,&02,&1C ; g = &00,&20,&20,&3C,&22,&22,&22,&22,&00,&00 ; h = &00,&08,&00,&18,&08,&08,&08,&1C,&00,&00 ; i = &00,&08,&00,&08,&08,&08,&08,&08,&08,&10 ; j = &00,&10,&10,&12,&14,&18,&14,&12,&00,&00 ; k = &00,&18,&08,&08,&08,&08,&08,&1C,&00,&00 ; l = &00,&00,&00,&34,&2A,&2A,&2A,&2A,&00,&00 ; m = &00,&00,&00,&3C,&22,&22,&22,&22,&00,&00 ; n = &00,&00,&00,&1C,&22,&22,&22,&1C,&00,&00 ; o = &00,&00,&00,&3C,&22,&22,&22,&3C,&20,&20 ; p = &00,&00,&00,&1E,&22,&22,&22,&1E,&02,&02 ; q = &00,&00,&00,&16,&18,&10,&10,&10,&00,&00 ; r = &00,&00,&00,&1E,&20,&1C,&02,&3C,&00,&00 ; s = &00,&08,&08,&1C,&08,&08,&08,&04,&00,&00 ; t = &00,&00,&00,&22,&22,&22,&22,&1E,&00,&00 ; u = &00,&00,&00,&22,&22,&14,&14,&08,&00,&00 ; v = &00,&00,&00,&22,&22,&2A,&2A,&14,&00,&00 ; w = &00,&00,&00,&22,&14,&08,&14,&22,&00,&00 ; x = &00,&00,&00,&22,&22,&22,&22,&1E,&02,&1C ; y = &00,&00,&00,&3E,&04,&08,&10,&3E,&00,&00 ; z = &00,&10,&10,&10,&10,&12,&06,&0A,&0E,&02 ; { = &00,&14,&14,&14,&14,&14,&14,&14,&00,&00 ; | = &00,&30,&08,&30,&08,&32,&06,&0A,&0E,&02 ; } = &00,&00,&08,&00,&3E,&00,&08,&00,&00,&00 ; ~ = &00,&3E,&3E,&3E,&3E,&3E,&3E,&3E,&00,&00 ; &FF ] END