Programming for the one and only universal graphics mode. --------------------------------------------------------- If you need to write a graphics routine that has a reasonable resolution and which is nearly always present, there is just one choice: mode 12h or the well known 640 x 480 x 16. This mode is the highest resolution mode which is always available in all VGA cards. 800 x 600 is better but it either needs a VESA driver installed or the user must himself figure out how to switch the machine to that mode. Not an easy task for the majority of "experienced Windows users" (isn't this a paradox?). Mode 12h is treated as a worst case by many Superior Operating Systems. But for most purposes it is just fine. It's fast, reasonably easy to use and it is omni present. That's why I decided to port my textmode windows to this graphics mode. The application. ---------------- I built a simple AD converter that measures voltages and converts them into digits. The ADC fits on a COM port and is completely controlled from software. The idea was to have different reference voltages, sample rates, scaling factors, a bar graph display and a 4 digit LED-style read-out. And in the bottom window there is a "recorder" that plots pixels in real-time. If all parts have been explained I might post the full package (the sources, the schematics and such) so that everyone can build one for your own. How to switch to Mode 12h? -------------------------- Going to mode 12h is easy. Just use the BIOS interrupt 10h as follows: mov ax, 012 int 010 and you're in. Remember, I use A86 syntax, so all numbers starting with a nought are considered hexadecimal. Plotting in a graphics screen. ------------------------------ Now that we're in Mode 012, we should also try to fill that clear black rectangle. But first we should define a way of remembering WHERE to put our cute little dots. For all my plotting, I use the following structure: -------------------------------- Window Information Block ------ Infoblk1 STRUC Win_X dw ? ; top-left window position, X and ... Win_Y dw ? ; ... Y Win_wid dw ? ; window width and ... Win_hgt dw ? ; ... height CurrX dw ? ; within window, current X-coordinate, ... CurrY dw ? ; ... and Y DeltaX dw ? DeltaY dw ? Indent dw ? ; Indentation for characters in PIXELS! Multiply dw ? ; screenwidth handler Watte01 dw ? ; BoxCol db ? ; border colour TxtCol db ? ; text colour BckCol db ? ; background colour MenuCol db ? ; menu text colour ENDS -------------------------------- Window Information Block ------ It will be clear after looking into this list, that each InfoBlock describes a window, a rectangular portion of the screen, which is treated as a unity. Each window is defined by the topleft (x,y) coordinates and the window width and height. Knowing these four words, the window is defined and fixed on screen. If the window is to be moved, just adjust the topleft (x,y) position. Since it is handy to know where in this window we are plotting, I defined two more X and Y values: "CurrX" and "CurrY". When a request to (un)plot is made, it will start on these coordinates. For line drawing and such there are the "DeltaX" and "DeltaY" variables. The former is for horizontal lines, the latter for vertical lines. Now that we have our fancy window, where we can plot and draw lines, we also need some text to see what it's all supposed to be about. The text is plotted at the CurrX and CurrY postions. Each character is PLOTTED there, so tokens can be put at ANY location on screen, not just on byte boundaries. For nice and easy allignments, I defined the variable "Indent" which defines how many pixels from the left or right margin must remain blank. Since this software should be as easy to adapt to other resolutions as possible, there is a need for a "Multiply" variable. This is filled with the offset address of a dedicated screen multiplier routine. In Mode 012 there are 640 pixels on a line. That's 80 bytes. So in order to calculate the pixel address you need to use the following formula: PixAddr = CurrY * 80 + CurrX / 8 So we need a set of damned fast Mul_80 routines. If needed you can make some of them and at init-time find out the CPU and hardware and assign a suitable routine and fill it in in the Window definition structures. The "Watte01" field is just a filler. Reserved by me. Since the Mode 012 has 16 colours to spare we should also use them. Therefore I set up space for 4 colours: Box-, Text-, Background- and Menu-colours. Each printing routine will make sure the right colour is set. It will be clear that each window is very flexible to use. If the position is wrong, just change a few numbers. Also if the colours are not optimal. And by having several windows assigned to the same area on screen, you can easily build special effects: fullscrn dw 0, 0,640,480, 0, 0, 0, 0, 4, mul_80, 0 db 12, 14, 3, 15 ; main screen window FullScrn just describes the complete screen. It is used for some very general printing an plotting tasks. It starts at topleft (0,0) and is 640 wide and 480 high. ParWin2 dw 5, 30,630,150, 8, 9, 0, 0, 4, mul_80, 0 db 10, 11, 3, 11 ; Parameter window This is a window which is a subwindow of the Full Screen for storing data and parameters. PlotWin dw 5,195,630,260, 0, 0, 0, 0, 4, mul_80, 0 db 9, 15, 3, 7 ; Virtual plotting window This is the Virtual Plotting Window. It has some text, plus the actual plotting window: PlotWin2 dw 6,196,628,256, 0, 0, 0, 0, 4, mul_80, 0 db 9, 15, 3, 7 ; Actual plotting window This is the place where the pixels live. It starts one pixel down/right of the virtual window and also ends one pixel short of it. The reason for making this "dummy" window structure was that this way there is no need for an elaborate checking of extreme ends of the window while erasing pixels. On the extremes of the "Virtual Plotting Window" there are the pixels that make up a nice coloured box. It looks not nice when these lines are erased. And the easiest way to prevent this was by defining two separate windows: one for constructing the box and one for the actual work. The 4 digit LED-style read-out is also controlled by four different windows. Each digit has its own window definition: ------------ Digit Space ------------------------------- Start --- DigSpac1 dw 16, 90, 40, 50, 0, 0, 0, 0, 0, mul_80, 0 db 9, 11, 14, 3 ; Digital display, digit 1, MSD DigSpac2 dw 56, 90, 40, 50, 0, 0, 0, 0, 0, mul_80, 0 db 9, 11, 14, 3 ; Digital display, digit 2 DigSpac3 dw 96, 90, 40, 50, 0, 0, 0, 0, 0, mul_80, 0 db 9, 11, 12, 3 ; Digital display. digit 3 DigSpac4 dw 136, 90, 40, 50, 0, 0, 0, 0, 0, mul_80, 0 db 9, 11, 12, 3 ; Digital display, digit 4, LSD MSD = Most Significant Digit LSD = Least Significant Digit ------------ Digit Space -------------------------------- End ---- This way it is convenient to allign the digits on screen. As with normal LED- style digits, the seven segments of them are drawn piece by piece. And erased if necessary. As you will know from voltmeters, the MSD is the least likely to change in time and the LSD is most likely to be different between any two samples. So in a way it is necessary to control erasing of just one digit without massive software overheads. Therefore I again chose to use a separate window for each digit. It makes erasing the digit easier and independent of the other three. Something else to observe is, that the two or three digits behind the decimal point have another colour from those before it. This way the user can easily see the approximate magnitude of the number without having to search for a decimal point. This is accomplished easily by having different BckCols in the LSD windows. This all costs a few bytes extra, but it saves a lot of coding. How to quickly load a segment register. --------------------------------------- Segment registers cannot be loaded with immediate data. So you normally put a register on the stack and use that to transfer the constant to the actual segment register. This is not necessary. It can be done much easier like below: VGA_base dw 0A000 ; for ease of loading segment registers And the corresponding code: mov es, [VGA_base] The detour via the stack or via AX takes more cycles and bytes. Defining what to print. ----------------------- In a graphics screen there are an awful lot of places where to store our text. So we need a way to define where to put which tokens. For this I use the following construct: -------------- Topic ----------------------------------- Start --- Topic MACRO ; start of printing message dw #1, #2 db #3, #4 #EM TopicEnd MACRO ; topics stop here dw 0F000 #EM Topic 180, 9, 'Start : ' ParaStrt db 'Manual ', 0 Topic 9, 28, 'Power : ' ParaPowr db 'OFF', 0 Topic 360, 55, 'Group : ' ParaGrup db '16 ', 0 TopicEnd -------------- Topic ------------------------------------ End ---- The Topic Macro puts the first two arguments (the new values for CurrX and CurrY) in the first two WORD positions of the definition table. The actual text is then put in the BYTE positions. In most cases there will be no #4 argument, but A86 doesn't care about that. Each "to-print" table is shut down by an EndTopic Macro. It defines a new CurrX of -4096. That clearly is out of range, so this is end of table. In normal operation, small negative values of CurrX and CurrY are accepted and taken care of, although it can be dangerous to use this feature. Multiplying by 80. ------------------ On all CPU's form the 486, the MUL instruction is single cycle, so it'll be damn fast. For all older CPU's, the following code could mean some significant speed increases: -------------------- Multiply ------------------------ Start ---- mul_80: push bx ; PixAddr in Mode 012 shl ax, 4 mov bx, ax ; bx = 16 x SCR_Y shl ax, 2 ; ax = 64 x SCR_Y add ax, bx ; ax = 80 x SCR_Y pop bx ret -------------------- Multiply ------------------------- End ----- This routine is used over and over again, so a few microseconds more or less will make a big difference. Where to leave our pixels? -------------------------- Suppose you need to plot pixel (3,0). That's an easy one. It will fit in the very first byte of the VGA memory array. It's segment is 0A000 and it's offset is plain 0. But not the full byte, since that would produce a line. No, we need to access bit 4 of byte 0. Yes, the first pixel is bit 7 of byte 0 and the 8th pixel is bit 0 of byte 0. Or, in index-language, CurrX = 0 addresses bit 7, and so on. So we need to invert the screenposition into a bitposition. We'll come to that later. Suppose, by some sheer magic, we succeeded in making that conversion, we still need to tell the VGA which bit is involved. That's done by means of the following routine: --------------------- SetMask ------------------------ Start ------- SetMask: push dx ; ah = mask mov dx, 03CE mov al, 8 out dx, ax ; set bit mask pop dx ret --------------------- SetMask ------------------------- End -------- This is an optimized routine. The VGA is a 16 bit card, so we can use 16 bit I/O instructions for adjacent I/O ports. The construct: mov al, 8 out dx, ax ; set bit mask is identical to: mov al, 8 out dx, al inc dx mov al, ah out dx, al Anyway, the plottingmask is defined to be as loaded in the AH register. We can put any value in AH, not just one pixel, but also "no pixels" and "all pixels". Defining colour in Mode 012. ---------------------------- Colours to use during plotting are defined in a comparable fashion: --------------------- Set Colour --------------------- Start ------- SetColr: push dx ; ah = colour mov dx, 03C4 mov al, 2 out dx, ax ; select page register and colour pop dx ret --------------------- Set Colour ---------------------- End -------- In Mode 013 you just can load a bytevalue colour into a memory location and that's it. So that's an ultrafast resolution, but at the price of resolution. In Mode 012 we define colour with a series of I/O instructions. If a colour got set, it remains active until canceled by another SetColr call. Try to remember this when all on a sudden all kinds of fancy colours start to appear on screen.... Where to put the pixel? ----------------------- I have presented the formula some paragrpahs before this one. Basically we work with virtual coordinates and must translate these to real coordinates before trying to calculate an address. This is done by: ------------------ VGA memory address ---------------- Start ------- VGaddr: ; calculate address in VGA memory mov es, [VGA_base] ; quickly load segment register mov ax, [di.CurrY] ; ax = current Y add ax, [di.Win_Y] ; adjust for window offset call [di.Multiply] ; multiply by bytes per row mov bx, [di.CurrX] ; bx = current X add bx, [di.Win_X] ; adjust for window offset shr bx, 3 ; divide by 8 add bx, ax ; bx = index address into video segment ret ------------------ VGA memory address ----------------- End -------- It's all fairly straightforward. How do we plot pixels in Mode 012? ---------------------------------- This is a silly process. We cannot access all the 4 colour planes at once, so we have used SetColr to define which colourplanes are to be affected. This all is rather complicated. You may either believe me on my word, or consult a 1200 page reference.... Now that we're ready to plot pixels, we do so by the following code: ------------------ VgaPlot -------------------- Start -------------- VgaPlot: mov al, [es:bx] ; Do the actual plotting mov al, [ToPlot] mov [es:bx], al ret ------------------ VgaPlot --------------------- End --------------- The first line is a read command. It notifies the VGA controller about the address of the pixelbyte. The resulting data from the read is of no concern. We immediately replace it with the value of "ToPlot". For plotting there is a value of "FF" in this byte and for erasing there is a "00" in it. After this comes the actual plotting function. The write to the specified address sets the pixels as defined by AL and SetMask. Adding it all up gives the following code to really plot a pixel: -------- PlotPix ------------------------------- Start ----------- PlotPix: push ax, bx, cx, es ; plot a point on screen call VGaddr mov cx, [di.CurrX] ; calculate plottingmask add cx, [di.Win_X] and cx, 0111xB ; cl = position in byte mov ah, 080 shr ah, cl ; now move the high bit backwards... call SetMask ; use it to set mask call VgaPlot ; and do the plotting pop es, cx, bx, ax ret -------- PlotPix -------------------------------- End ------------ That's it to plot a pixel: just a few calls to some procedures we defined earlier on. The msjority of this procedure is comprised of the way to find the actual bit-position in the VGA memory byte. Remember, to plot pixel 0 we need bit 7! Therefore we load CX with the current X value, correct this for the current window position and isolate the lower 3 bits. These indicate the position of the pixel in screenmemory. mov cx, [di.CurrX] ; calculate plottingmask add cx, [di.Win_X] and cx, 0111xB ; cl = position in byte At this point, CL contains the n-th bit in this byte. So I load AH with the binary pattern 10000000 and shift it right until the corresponding bit position is reached: mov ah, 080 shr ah, cl ; now move the high bit backwards... I don't know if there are batches of Intel CPU's that have a problem with the SHR instruction is CL equals zero, but I have not yet noticed any. Lines: series of pixels. ------------------------ There are three kinds of lines: horizontal, vertical and sloped ones. Vertical lines are plotted pixel by pixel since all of them end up in different bytes of VGA memory. Sloped lines are best taken care of by a Bresenham-style line drawing algorithm (although the digital differential analyser is better). Horizontal lines are a different kind of line. In these, several adjacent pixels are plotted. And adjacent pixels mainly are in the same VGA memory byte. Therefore I made two horizontal line drawers. The one for short lines (less than 17 pixels) just plots the pixels one by one. The other algorithm, for lines of 17 pixels or more, tries to fill VGA memory with as much byte writes as possible. Taking care of longer horizontal lines. --------------------------------------- Suppose our line is composed as follows: First 1 2 3 ... K Last ; byte in video memory ......## ######## ######## ###...### ###..... ; # = pixel to be set So our line starts at pixel 6 (i.e. bit 1) of VGA memory byte "First". Next it lasts for N pixels and the last pixel to plot is pixel 2 (or bit 5). We need some variables to calculate how to proceed with this in the shortest possible time. This needs some calculations, so for short lines the math overhead is more work than the actual plotting will take up. First 1 2 3 ... K Last ; byte in video memory ......## ######## ######## ###...### ###..... ; # = pixel to be set We first need to know the E-value which describes the number of pixels to plot in the very first byte. The E-value is calculated as follows: E-val = 8 - ((CurrX + Win_X) AND 7) Now we know the number of pixels to plot in the very first VGA memory location. It would however come in handy if we would know with which plotting mask this would correspond. That's why we use it to derive the E-mask: E-mask = FF shr ((8 - E-val) AND 7) Next we need to know how many pixels there need to be plotted in the last memory location. L-value and L-mask are determined as follows: L-val = (Total - E-val) AND 7 L-mask = 080 sar L-val With the SAR we shift signbits to the right until the number of pixels corresponds with the number of bits in the mask. The last parameter we need to know is the actual speeding-up part: the full bytes that can be plotted. The octet-part of the routine. We do this as follows: K-val = (T - E-val - L-val)/8 Now it also becomes clear why I kept the E-val and L-val parameters. They're just needed for getting the right value for K-val. There is, however one exceptional situation. Suppose the line we need to plot is 26 pixels long, starting at pixel 6. This would produce the values: E-val = 2 E-mask = 00000011 L-val = (26 - 2) AND 7 = 24 AND 7 = 0 L-mask = 00000000 K-val = (26 - 2 - 0)/8 = 3 So, if the line ends on a byte boundary, we may NOT try to plot of pixels past it (in a plotting loop that starts with CX = 0). What the H_line procedure does is no more than what I decribed above. Here comes the source: -------- H_Line -------------------------------- Start ----------- L0: mov cx, [di.DeltaX] ; do a short line L1: call PlotPix ; by just repeating a single pixel- inc [di.CurrX] ; plot and update of CurrX loop L1 ; until done pop es, cx, bx, ax ret H_Line: push ax, bx, cx, es ; optimized horizontal line drawing cmp [di.DeltaX], 17 ; too few pixels for a bulk draw? jb L0 mov cx, [di.CurrX] ; do a long line add cx, [di.Win_X] ; first get the E-value as described and cx, 0111xB ; above mov bx, 8 sub bx, cx mov [E_val], bx ; pixels to plot in leftmost byte mov al, 0FF ; now compose the mask to use there shr al, cl mov [E_mask], al ; and store it in memory mov cx, [di.DeltaX] ; CX = length of line sub cx, [E_val] ; compensate for first-byte pixels mov ax, cx and ax, 0111xB ; this many pixels in rigthmost byte mov [L_val], ax ; and store it in memory sub cx, ax ; CX = number of pixels inbetween shr cx, 3 ; divide by 8 pixels per byte mov [K_val], cx ; number of "full" bytes to plot clr al ; AL := 0 mov cx, [L_val] ; prepare to compose L-mask cmp cx, 0 ; any bits in "last byte" IF ne mov al, bit 7 ; if any bits, setup AH register dec cx ; compensate for pixel 0, ... sar al, cl ; ... compose plotting mask and ... mov [L_mask], al ; ... store it into memory. ; that's it. Let's plot! call VGaddr ; load BX with address of byte in ; VGA memory mov ah, [E_mask] call SetMask ; set plotting mask and ... call VgaPlot ; ... plot leftmost part inc bx ; get adjacent address mov cx, [K_val] ; prepare for bulk-filling jcxz >L4 ; if nothing to do, jump out mov ah, 0FF ; else set ALL PIXELS mask call SetMask L3: call VgaPlot ; plot middle part inc bx loop L3 ; until done L4: mov ah, [L_mask] call SetMask call VgaPlot ; plot remaining pixels mov ax, [di.DeltaX] add [di.CurrX], ax ; make sure CurrX is updated pop es, cx, bx, ax ; and git outa'here ret -------- H_Line --------------------------------- End ------------ The preparations are the bulk of the work, but after that is done, the line is plotted with the lowest amount of I/O overhead. Vertical lines. --------------- Vertical lines are simply plot by repeatedly calling PlotPix. It's so simple that neither need nor want to elaborate on it: -------- VertLin ------------------------------- Start ----------- VertLin: push cx ; draw a vertical line mov cx, [di.DeltaY] L0: call PlotPix inc [di.CurrY] ; adjust Y coordinate loop L0 ; but not X value! pop cx ret -------- VertLin -------------------------------- End ------------ What to do with linedrawing functions? -------------------------------------- Now that we can draw lines, we can also draw boxes and window borders. This all looks very professional and the overview of a program is enhanced considerably. Try to figure out how to make the box-drawers by yourself. Plotting text. -------------- Now that we have windows that can be put at any plotting position, we also need to be able to position text at any position. It doesn't look nice if different windows force text to default to byte boundaries. And with the experience we got from the H_line function, we are able to make a character plotter that puts text on screen at ANY position. I use a 9 x 16 character set. The nineth bit is just always blank, but it enhances readability considerably. The pixels in the bitmap are all 8 bits wide and 16 pixels tall. In exceptional cases, the bitmaps can be plotted at byte boundaries. In 85+ % of the time this will not be the case. Therefore I do the following: - do some positioning math first - repeat 16 times: - load the byte of the bitmap in AH - shift AX to the right the correct number of pixels - plot the AH part - if plotting on a byte boundary, we're done, else - repeat 16 times: - load the byte of the bitmap in AH - shift AX to the right the correct number of pixels - plot the AL part Let's just have a look: -------- PutChar ------------------------------- Start ----------- L0: add [di.CurrY], 16 ; process 'LF' L1: pop es, si, cx, bx ret L2: mov bx, [di.Indent] ; process 'CR' mov [di.CurrX], bx jmp L1 PutChar: push bx, cx, si, es ; print char in al at (x,y) cmp al, lf je L0 cmp al, cr je L2 mov bx, [di.CurrX] add bx, CHR_WID cmp bx, [di.Win_wid] ; still safe to print character? jbe >L3 ; if so, skip over this part mov bx, [di.Indent] mov [di.CurrX], bx ; mimick 'CR' add [di.CurrY], 16 ; mimick 'LF' L3: mov cx, [di.CurrX] add cx, [di.Win_X] and cx, 0111xB mov [C_val], cl ; store shiftcount for masks mov bx, 0FF00 shr bx, cl ; setup plotting mask and ... mov [P_mask], bx ; ... store it clr ah ; ax = ASCII code mov si, ax ; make address of pixels in bitmap shl si, 4 add si, offset bitmap call VGaddr ; bx = -> in video memory mov ax, [P_mask] ; only the AH part is used ... call SetMask ; ... here. mov cx, 16 ; 16 pixel lines per token L4: push cx ; we're in the loop now mov ah, [si] ; AH = pixelpattern clr al ; AL = empty mov cl, [C_val] ; get shiftcount shr ax, cl ; distribute pixelBYTE across a WORD mov cl, [es:bx] ; dummy read, CL is expendable mov [es:bx], ah ; actual plotting of this half add bx, 80 ; point to next pixelbyte address inc si ; next pixeldata address pop cx loop L4 ; and loop back sub bx, 16 * 80 - 1 ; back to original position mov ax, [P_mask] cmp al, 0 ; if nothing to do, ... je >L6 ; ... skip this chapter mov ah, al ; else repeat the lot for the right- call SetMask ; most pixels.... mov cx, 16 sub si, cx ; correct SI L5: push cx mov ah, [si] clr al mov cl, [C_val] shr ax, cl mov cl, [es:bx] mov [es:bx], al add bx, 80 inc si pop cx loop L5 L6: add [di.CurrX], CHR_WID ; adjust CurrX value before ... jmp L1 ; ... getting a hike -------- PutChar -------------------------------- End ------------ So far for plotting text. This routine will dump any character in any place of the graphics screen. But it needs a CurrX and a CurrY value to know where to plot things. This is both an advantage and a disadvantage. The advantage is that we can plot ANYWHERE we like. The disadvantage is that we need to elaborately specify CurrX and CurrY before the text is where we would like to have it. That's why I made the constrcut with the Topic and TopicEnd macro's, as described above. Here comes the code for printing a table on screen. We spent a lot of time on the preparations, and this is the stage where it is going to pay off. Look how much code we need for printing neat sets of tokens and characters on screen. -------- Print --------------------------------- Start ----------- print: mov ah, [di.TxtCol] ; print a table of text call SetColr L0: lodsw ; get Xpos cmp ax, 0F000 ; end of table? je ret ; exit, if so mov [di.CurrX], ax lodsw ; get Ypos mov [di.CurrY], ax L1: lodsb ; get text cmp al, 0 je L0 call putchar ; and print it jmp L1 ; until this line is done -------- Print ---------------------------------- End ------------ Wit this approach, and starting from a working (empty) framework of routines, you can design the userinterface of your software within the hour. And it will look just fine. The actual code is then the only thing you need to worry about..... Having such routines, which have been tested and found reliable, you make the user interface easily and are able to concentrate on the actual coding the maximum amount of time. If the screen needs another layout (since you couldn't realize the function you considered), just change a few entries in the table. Many times just the X or Y values need some adjustment for better lining up, or for regrouping. No need to worry about the order of the plotting. Just make sure that the correct window is selected (for the colours) and that the table is terminated by a TopicEnd. Conclusion. ----------- So far my elaboration on the VGA mode 12h. Again, I would rather use 800 x 600 but that mode is not standardised. VGA 12h is standard on all VGA cards, so it's the best we can universally get and for many applications it is more than enough. Please try to make the BoxDrawing function. I will submit the "solution" to the next issue. For future issues I will start working on an explanation about mouse-usage. This little rodent is nice to control many applications. If the screen is well layed out, you just don't need the keyboard for data entry. Just drag the mouse along the screen and poke him in the eye. Here comes the bitmapdata for the character generator: ------- BitMap --------------------------------- Start ----------- bitmap: .NOLIST db 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; ^0 db 000, 000, 07E, 081, 0A5, 081, 081, 0BD, 099, 081, 081, 07E, 000, 000, 000, 000 ; ^A db 000, 000, 07E, 0FF, 0DB, 0FF, 0FF, 0C3, 0E7, 0FF, 0FF, 07E, 000, 000, 000, 000 ; ^B db 000, 000, 000, 000, 06C, 0FE, 0FE, 0FE, 0FE, 07C, 038, 010, 000, 000, 000, 000 ; ^C db 000, 000, 000, 000, 010, 038, 07C, 0FE, 07C, 038, 010, 000, 000, 000, 000, 000 ; ^D db 000, 000, 000, 018, 03C, 03C, 0E7, 0E7, 0E7, 018, 018, 03C, 000, 000, 000, 000 ; ^E db 000, 000, 000, 018, 03C, 07E, 0FF, 0FF, 07E, 018, 018, 03C, 000, 000, 000, 000 ; ^F db 000, 000, 000, 000, 000, 000, 018, 03C, 03C, 018, 000, 000, 000, 000, 000, 000 ; ^G db 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0E7, 0C3, 0C3, 0E7, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF ; ^H db 000, 000, 000, 000, 000, 03C, 066, 042, 042, 066, 03C, 000, 000, 000, 000, 000 ; ^I db 0FF, 0FF, 0FF, 0FF, 0FF, 0C3, 099, 0BD, 0BD, 099, 0C3, 0FF, 0FF, 0FF, 0FF, 0FF ; ^J db 000, 000, 01E, 00E, 01A, 032, 078, 0CC, 0CC, 0CC, 0CC, 078, 000, 000, 000, 000 ; ^K db 000, 000, 03C, 066, 066, 066, 066, 03C, 018, 07E, 018, 018, 000, 000, 000, 000 ; ^L db 000, 000, 03F, 033, 03F, 030, 030, 030, 030, 070, 0F0, 0E0, 000, 000, 000, 000 ; ^M db 000, 000, 07F, 063, 07F, 063, 063, 063, 063, 067, 0E7, 0E6, 0C0, 000, 000, 000 ; ^N db 000, 000, 000, 018, 018, 0DB, 03C, 0E7, 03C, 0DB, 018, 018, 000, 000, 000, 000 ; ^O db 000, 080, 0C0, 0E0, 0F0, 0F8, 0FE, 0F8, 0F0, 0E0, 0C0, 080, 000, 000, 000, 000 ; ^P db 000, 002, 006, 00E, 01E, 03E, 0FE, 03E, 01E, 00E, 006, 002, 000, 000, 000, 000 ; ^Q db 000, 000, 018, 03C, 07E, 018, 018, 018, 07E, 03C, 018, 000, 000, 000, 000, 000 ; ^R db 000, 000, 066, 066, 066, 066, 066, 066, 066, 000, 066, 066, 000, 000, 000, 000 ; ^S db 000, 000, 07F, 0DB, 0DB, 0DB, 07B, 01B, 01B, 01B, 01B, 01B, 000, 000, 000, 000 ; ^T db 000, 07C, 0C6, 060, 038, 06C, 0C6, 0C6, 06C, 038, 00C, 0C6, 07C, 000, 000, 000 ; ^U db 000, 000, 000, 000, 000, 000, 000, 000, 0FE, 0FE, 0FE, 0FE, 000, 000, 000, 000 ; ^V db 000, 000, 018, 03C, 07E, 018, 018, 018, 07E, 03C, 018, 07E, 000, 000, 000, 000 ; ^W db 000, 000, 018, 03C, 07E, 018, 018, 018, 018, 018, 018, 018, 000, 000, 000, 000 ; ^X db 000, 000, 018, 018, 018, 018, 018, 018, 018, 07E, 03C, 018, 000, 000, 000, 000 ; ^Y db 000, 000, 000, 000, 000, 018, 00C, 0FE, 00C, 018, 000, 000, 000, 000, 000, 000 ; ^Z db 000, 000, 000, 000, 000, 030, 060, 0FE, 060, 030, 000, 000, 000, 000, 000, 000 ; ^[ db 000, 000, 000, 000, 000, 000, 0C0, 0C0, 0C0, 0FE, 000, 000, 000, 000, 000, 000 ; ^\ db 000, 000, 000, 000, 000, 028, 06C, 0FE, 06C, 028, 000, 000, 000, 000, 000, 000 ; ^] db 000, 000, 000, 000, 010, 038, 038, 07C, 07C, 0FE, 0FE, 000, 000, 000, 000, 000 ; ^^ db 000, 000, 000, 000, 0FE, 0FE, 07C, 07C, 038, 038, 010, 000, 000, 000, 000, 000 ; ^_ db 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; < > db 000, 000, 018, 03C, 03C, 03C, 018, 018, 018, 000, 018, 018, 000, 000, 000, 000 ; ! db 000, 066, 066, 066, 024, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; " db 000, 000, 000, 06C, 06C, 0FE, 06C, 06C, 06C, 0FE, 06C, 06C, 000, 000, 000, 000 ; # db 018, 018, 07C, 0C6, 0C2, 0C0, 07C, 006, 006, 086, 0C6, 07C, 018, 018, 000, 000 ; $ db 000, 000, 000, 000, 0C2, 0C6, 00C, 018, 030, 060, 0C6, 086, 000, 000, 000, 000 ; % db 000, 000, 038, 06C, 06C, 038, 076, 0DC, 0CC, 0CC, 0CC, 076, 000, 000, 000, 000 ; & db 000, 030, 030, 030, 060, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; ' db 000, 000, 00C, 018, 030, 030, 030, 030, 030, 030, 018, 00C, 000, 000, 000, 000 ; ( db 000, 000, 030, 018, 00C, 00C, 00C, 00C, 00C, 00C, 018, 030, 000, 000, 000, 000 ; ) db 000, 000, 000, 000, 000, 066, 03C, 0FF, 03C, 066, 000, 000, 000, 000, 000, 000 ; * db 000, 000, 000, 000, 000, 018, 018, 07E, 018, 018, 000, 000, 000, 000, 000, 000 ; + db 000, 000, 000, 000, 000, 000, 000, 000, 000, 018, 018, 018, 030, 000, 000, 000 ; , db 000, 000, 000, 000, 000, 000, 0FE, 0FE, 000, 000, 000, 000, 000, 000, 000, 000 ; - db 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 018, 018, 000, 000, 000, 000 ; . db 000, 000, 000, 000, 002, 006, 00C, 018, 030, 060, 0C0, 080, 000, 000, 000, 000 ; / db 000, 000, 038, 06C, 0C6, 0C6, 0D6, 0D6, 0C6, 0C6, 06C, 038, 000, 000, 000, 000 ; 0 db 000, 000, 018, 038, 078, 018, 018, 018, 018, 018, 018, 07E, 000, 000, 000, 000 ; 1 db 000, 000, 07C, 0C6, 006, 00C, 018, 030, 060, 0C0, 0C6, 0FE, 000, 000, 000, 000 ; 2 db 000, 000, 07C, 0C6, 006, 006, 03C, 006, 006, 006, 0C6, 07C, 000, 000, 000, 000 ; 3 db 000, 000, 00C, 01C, 03C, 06C, 0CC, 0FE, 00C, 00C, 00C, 01E, 000, 000, 000, 000 ; 4 db 000, 000, 0FE, 0C0, 0C0, 0C0, 0FC, 006, 006, 006, 0C6, 07C, 000, 000, 000, 000 ; 5 db 000, 000, 038, 060, 0C0, 0C0, 0FC, 0C6, 0C6, 0C6, 0C6, 07C, 000, 000, 000, 000 ; 6 db 000, 000, 0FE, 0C6, 006, 006, 00C, 018, 030, 030, 030, 030, 000, 000, 000, 000 ; 7 db 000, 000, 07C, 0C6, 0C6, 0C6, 07C, 0C6, 0C6, 0C6, 0C6, 07C, 000, 000, 000, 000 ; 8 db 000, 000, 07C, 0C6, 0C6, 0C6, 07E, 006, 006, 006, 00C, 078, 000, 000, 000, 000 ; 9 db 000, 000, 000, 000, 000, 018, 018, 000, 000, 000, 018, 018, 000, 000, 000, 000 ; : db 000, 000, 000, 000, 018, 018, 000, 000, 000, 018, 018, 030, 000, 000, 000, 000 ; ; db 000, 000, 000, 006, 00C, 018, 030, 060, 030, 018, 00C, 006, 000, 000, 000, 000 ; < db 000, 000, 000, 000, 000, 07E, 000, 000, 07E, 000, 000, 000, 000, 000, 000, 000 ; = db 000, 000, 000, 060, 030, 018, 00C, 006, 00C, 018, 030, 060, 000, 000, 000, 000 ; > db 000, 000, 07C, 0C6, 0C6, 00C, 018, 018, 018, 000, 018, 018, 000, 000, 000, 000 ; ? db 000, 000, 000, 07C, 0C6, 0C6, 0DE, 0DE, 0DE, 0DC, 0C0, 07C, 000, 000, 000, 000 ; @ db 000, 000, 010, 038, 06C, 0C6, 0C6, 0FE, 0C6, 0C6, 0C6, 0C6, 000, 000, 000, 000 ; A db 000, 000, 0FC, 066, 066, 066, 07C, 066, 066, 066, 066, 0FC, 000, 000, 000, 000 ; B db 000, 000, 03C, 066, 0C2, 0C0, 0C0, 0C0, 0C0, 0C2, 066, 03C, 000, 000, 000, 000 ; C db 000, 000, 0F8, 06C, 066, 066, 066, 066, 066, 066, 06C, 0F8, 000, 000, 000, 000 ; D db 000, 000, 0FE, 066, 062, 068, 078, 068, 060, 062, 066, 0FE, 000, 000, 000, 000 ; E db 000, 000, 0FE, 066, 062, 068, 078, 068, 060, 060, 060, 0F0, 000, 000, 000, 000 ; F db 000, 000, 03C, 066, 0C2, 0C0, 0C0, 0DE, 0C6, 0C6, 066, 03A, 000, 000, 000, 000 ; G db 000, 000, 0C6, 0C6, 0C6, 0C6, 0FE, 0C6, 0C6, 0C6, 0C6, 0C6, 000, 000, 000, 000 ; H db 000, 000, 03C, 018, 018, 018, 018, 018, 018, 018, 018, 03C, 000, 000, 000, 000 ; I db 000, 000, 01E, 00C, 00C, 00C, 00C, 00C, 0CC, 0CC, 0CC, 078, 000, 000, 000, 000 ; J db 000, 000, 0E6, 066, 066, 06C, 078, 078, 06C, 066, 066, 0E6, 000, 000, 000, 000 ; K db 000, 000, 0F0, 060, 060, 060, 060, 060, 060, 062, 066, 0FE, 000, 000, 000, 000 ; L db 000, 000, 0C6, 0EE, 0FE, 0FE, 0D6, 0C6, 0C6, 0C6, 0C6, 0C6, 000, 000, 000, 000 ; M db 000, 000, 0C6, 0E6, 0F6, 0FE, 0DE, 0CE, 0C6, 0C6, 0C6, 0C6, 000, 000, 000, 000 ; N db 000, 000, 07C, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 07C, 000, 000, 000, 000 ; O db 000, 000, 0FC, 066, 066, 066, 07C, 060, 060, 060, 060, 0F0, 000, 000, 000, 000 ; P db 000, 000, 07C, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 0D6, 0DE, 07C, 00C, 00E, 000, 000 ; Q db 000, 000, 0FC, 066, 066, 066, 07C, 06C, 066, 066, 066, 0E6, 000, 000, 000, 000 ; R db 000, 000, 07C, 0C6, 0C6, 060, 038, 00C, 006, 0C6, 0C6, 07C, 000, 000, 000, 000 ; S db 000, 000, 07E, 07E, 05A, 018, 018, 018, 018, 018, 018, 03C, 000, 000, 000, 000 ; T db 000, 000, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 07C, 000, 000, 000, 000 ; U db 000, 000, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 06C, 038, 010, 000, 000, 000, 000 ; V db 000, 000, 0C6, 0C6, 0C6, 0C6, 0D6, 0D6, 0D6, 0FE, 0EE, 06C, 000, 000, 000, 000 ; W db 000, 000, 0C6, 0C6, 06C, 07C, 038, 038, 07C, 06C, 0C6, 0C6, 000, 000, 000, 000 ; X db 000, 000, 066, 066, 066, 066, 03C, 018, 018, 018, 018, 03C, 000, 000, 000, 000 ; Y db 000, 000, 0FE, 0C6, 086, 00C, 018, 030, 060, 0C2, 0C6, 0FE, 000, 000, 000, 000 ; Z db 000, 000, 03C, 030, 030, 030, 030, 030, 030, 030, 030, 03C, 000, 000, 000, 000 ; [ db 000, 000, 000, 080, 0C0, 0E0, 070, 038, 01C, 00E, 006, 002, 000, 000, 000, 000 ; \ db 000, 000, 03C, 00C, 00C, 00C, 00C, 00C, 00C, 00C, 00C, 03C, 000, 000, 000, 000 ; ] db 010, 038, 06C, 0C6, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; ^ db 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 0FF, 0FF, 000, 000 ; _ db 030, 030, 018, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; ` db 000, 000, 000, 000, 000, 078, 00C, 07C, 0CC, 0CC, 0CC, 076, 000, 000, 000, 000 ; a db 000, 000, 0E0, 060, 060, 078, 06C, 066, 066, 066, 066, 07C, 000, 000, 000, 000 ; b db 000, 000, 000, 000, 000, 07C, 0C6, 0C0, 0C0, 0C0, 0C6, 07C, 000, 000, 000, 000 ; c db 000, 000, 01C, 00C, 00C, 03C, 06C, 0CC, 0CC, 0CC, 0CC, 076, 000, 000, 000, 000 ; d db 000, 000, 000, 000, 000, 07C, 0C6, 0FE, 0C0, 0C0, 0C6, 07C, 000, 000, 000, 000 ; e db 000, 000, 038, 06C, 064, 060, 0F0, 060, 060, 060, 060, 0F0, 000, 000, 000, 000 ; f db 000, 000, 000, 000, 000, 076, 0CC, 0CC, 0CC, 0CC, 0CC, 07C, 00C, 0CC, 078, 000 ; g db 000, 000, 0E0, 060, 060, 06C, 076, 066, 066, 066, 066, 0E6, 000, 000, 000, 000 ; h db 000, 000, 018, 018, 000, 038, 018, 018, 018, 018, 018, 03C, 000, 000, 000, 000 ; i db 000, 000, 006, 006, 000, 00E, 006, 006, 006, 006, 006, 006, 066, 066, 03C, 000 ; j db 000, 000, 0E0, 060, 060, 066, 06C, 078, 078, 06C, 066, 0E6, 000, 000, 000, 000 ; k db 000, 000, 038, 018, 018, 018, 018, 018, 018, 018, 018, 03C, 000, 000, 000, 000 ; l db 000, 000, 000, 000, 000, 0EC, 0FE, 0D6, 0D6, 0D6, 0D6, 0C6, 000, 000, 000, 000 ; m db 000, 000, 000, 000, 000, 0DC, 066, 066, 066, 066, 066, 066, 000, 000, 000, 000 ; n db 000, 000, 000, 000, 000, 07C, 0C6, 0C6, 0C6, 0C6, 0C6, 07C, 000, 000, 000, 000 ; o db 000, 000, 000, 000, 000, 0DC, 066, 066, 066, 066, 066, 07C, 060, 060, 0F0, 000 ; p db 000, 000, 000, 000, 000, 076, 0CC, 0CC, 0CC, 0CC, 0CC, 07C, 00C, 00C, 01E, 000 ; q db 000, 000, 000, 000, 000, 0DC, 076, 066, 060, 060, 060, 0F0, 000, 000, 000, 000 ; r db 000, 000, 000, 000, 000, 07C, 0C6, 060, 038, 00C, 0C6, 07C, 000, 000, 000, 000 ; s db 000, 000, 010, 030, 030, 0FC, 030, 030, 030, 030, 036, 01C, 000, 000, 000, 000 ; t db 000, 000, 000, 000, 000, 0CC, 0CC, 0CC, 0CC, 0CC, 0CC, 076, 000, 000, 000, 000 ; u db 000, 000, 000, 000, 000, 066, 066, 066, 066, 066, 03C, 018, 000, 000, 000, 000 ; v db 000, 000, 000, 000, 000, 0C6, 0C6, 0D6, 0D6, 0D6, 0FE, 06C, 000, 000, 000, 000 ; w db 000, 000, 000, 000, 000, 0C6, 06C, 038, 038, 038, 06C, 0C6, 000, 000, 000, 000 ; x db 000, 000, 000, 000, 000, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 07E, 006, 00C, 0F8, 000 ; y db 000, 000, 000, 000, 000, 0FE, 0CC, 018, 030, 060, 0C6, 0FE, 000, 000, 000, 000 ; z db 000, 000, 00E, 018, 018, 018, 070, 018, 018, 018, 018, 00E, 000, 000, 000, 000 ; { db 000, 000, 018, 018, 018, 018, 000, 018, 018, 018, 018, 018, 000, 000, 000, 000 ; | db 000, 000, 070, 018, 018, 018, 00E, 018, 018, 018, 018, 070, 000, 000, 000, 000 ; } db 000, 000, 076, 0DC, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; ~ db 000, 000, 000, 000, 010, 038, 06C, 0C6, 0C6, 0C6, 0FE, 000, 000, 000, 000, 000 ; DEL db 000, 000, 03C, 066, 0C2, 0C0, 0C0, 0C0, 0C2, 066, 03C, 00C, 006, 07C, 000, 000 ; db 000, 000, 0CC, 000, 000, 0CC, 0CC, 0CC, 0CC, 0CC, 0CC, 076, 000, 000, 000, 000 ; db 000, 00C, 018, 030, 000, 07C, 0C6, 0FE, 0C0, 0C0, 0C6, 07C, 000, 000, 000, 000 ; db 000, 010, 038, 06C, 000, 078, 00C, 07C, 0CC, 0CC, 0CC, 076, 000, 000, 000, 000 ; db 000, 000, 0CC, 000, 000, 078, 00C, 07C, 0CC, 0CC, 0CC, 076, 000, 000, 000, 000 ; db 000, 060, 030, 018, 000, 078, 00C, 07C, 0CC, 0CC, 0CC, 076, 000, 000, 000, 000 ; db 000, 038, 06C, 038, 000, 078, 00C, 07C, 0CC, 0CC, 0CC, 076, 000, 000, 000, 000 ; db 000, 000, 000, 000, 03C, 066, 060, 060, 066, 03C, 00C, 006, 03C, 000, 000, 000 ; db 000, 010, 038, 06C, 000, 07C, 0C6, 0FE, 0C0, 0C0, 0C6, 07C, 000, 000, 000, 000 ; db 000, 000, 0C6, 000, 000, 07C, 0C6, 0FE, 0C0, 0C0, 0C6, 07C, 000, 000, 000, 000 ; db 000, 060, 030, 018, 000, 07C, 0C6, 0FE, 0C0, 0C0, 0C6, 07C, 000, 000, 000, 000 ; db 000, 000, 066, 000, 000, 038, 018, 018, 018, 018, 018, 03C, 000, 000, 000, 000 ; db 000, 018, 03C, 066, 000, 038, 018, 018, 018, 018, 018, 03C, 000, 000, 000, 000 ; db 000, 060, 030, 018, 000, 038, 018, 018, 018, 018, 018, 03C, 000, 000, 000, 000 ; db 000, 0C6, 000, 010, 038, 06C, 0C6, 0C6, 0FE, 0C6, 0C6, 0C6, 000, 000, 000, 000 ; db 038, 06C, 038, 000, 038, 06C, 0C6, 0C6, 0FE, 0C6, 0C6, 0C6, 000, 000, 000, 000 ; db 018, 030, 060, 000, 0FE, 066, 060, 07C, 060, 060, 066, 0FE, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 0CC, 076, 036, 07E, 0D8, 0D8, 06E, 000, 000, 000, 000 ; db 000, 000, 03E, 06C, 0CC, 0CC, 0FE, 0CC, 0CC, 0CC, 0CC, 0CE, 000, 000, 000, 000 ; db 000, 010, 038, 06C, 000, 07C, 0C6, 0C6, 0C6, 0C6, 0C6, 07C, 000, 000, 000, 000 ; db 000, 000, 0C6, 000, 000, 07C, 0C6, 0C6, 0C6, 0C6, 0C6, 07C, 000, 000, 000, 000 ; db 000, 060, 030, 018, 000, 07C, 0C6, 0C6, 0C6, 0C6, 0C6, 07C, 000, 000, 000, 000 ; db 000, 030, 078, 0CC, 000, 0CC, 0CC, 0CC, 0CC, 0CC, 0CC, 076, 000, 000, 000, 000 ; db 000, 060, 030, 018, 000, 0CC, 0CC, 0CC, 0CC, 0CC, 0CC, 076, 000, 000, 000, 000 ; db 000, 000, 0C6, 000, 000, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 07E, 006, 00C, 078, 000 ; db 000, 0C6, 000, 07C, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 07C, 000, 000, 000, 000 ; db 000, 0C6, 000, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 07C, 000, 000, 000, 000 ; db 000, 018, 018, 03C, 066, 060, 060, 060, 066, 03C, 018, 018, 000, 000, 000, 000 ; db 000, 038, 06C, 064, 060, 0F0, 060, 060, 060, 060, 0E6, 0FC, 000, 000, 000, 000 ; db 000, 000, 066, 066, 03C, 018, 07E, 018, 07E, 018, 018, 018, 000, 000, 000, 000 ; db 000, 0F8, 0CC, 0CC, 0F8, 0C4, 0CC, 0DE, 0CC, 0CC, 0CC, 0C6, 000, 000, 000, 000 ; db 000, 00E, 01B, 018, 018, 018, 07E, 018, 018, 018, 018, 018, 0D8, 070, 000, 000 ; db 000, 018, 030, 060, 000, 078, 00C, 07C, 0CC, 0CC, 0CC, 076, 000, 000, 000, 000 ; db 000, 00C, 018, 030, 000, 038, 018, 018, 018, 018, 018, 03C, 000, 000, 000, 000 ; db 000, 018, 030, 060, 000, 07C, 0C6, 0C6, 0C6, 0C6, 0C6, 07C, 000, 000, 000, 000 ; db 000, 018, 030, 060, 000, 0CC, 0CC, 0CC, 0CC, 0CC, 0CC, 076, 000, 000, 000, 000 ; db 000, 000, 076, 0DC, 000, 0DC, 066, 066, 066, 066, 066, 066, 000, 000, 000, 000 ; db 076, 0DC, 000, 0C6, 0E6, 0F6, 0FE, 0DE, 0CE, 0C6, 0C6, 0C6, 000, 000, 000, 000 ; db 000, 03C, 06C, 06C, 03E, 000, 07E, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; db 000, 038, 06C, 06C, 038, 000, 07C, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; db 000, 000, 030, 030, 000, 030, 030, 060, 0C0, 0C6, 0C6, 07C, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 000, 0FE, 0C0, 0C0, 0C0, 0C0, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 000, 0FE, 006, 006, 006, 006, 000, 000, 000, 000, 000 ; db 000, 0C0, 0C0, 0C2, 0C6, 0CC, 018, 030, 060, 0DC, 086, 00C, 018, 03E, 000, 000 ; db 000, 0C0, 0C0, 0C2, 0C6, 0CC, 018, 030, 066, 0CE, 09E, 03E, 006, 006, 000, 000 ; db 000, 000, 018, 018, 000, 018, 018, 018, 03C, 03C, 03C, 018, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 036, 06C, 0D8, 06C, 036, 000, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 0D8, 06C, 036, 06C, 0D8, 000, 000, 000, 000, 000, 000 ; db 011, 044, 011, 044, 011, 044, 011, 044, 011, 044, 011, 044, 011, 044, 011, 044 ; db 055, 0AA, 055, 0AA, 055, 0AA, 055, 0AA, 055, 0AA, 055, 0AA, 055, 0AA, 055, 0AA ; db 0DD, 077, 0DD, 077, 0DD, 077, 0DD, 077, 0DD, 077, 0DD, 077, 0DD, 077, 0DD, 077 ; db 018, 018, 018, 018, 018, 018, 018, 018, 018, 018, 018, 018, 018, 018, 018, 018 ; db 018, 018, 018, 018, 018, 018, 018, 0F8, 018, 018, 018, 018, 018, 018, 018, 018 ; db 018, 018, 018, 018, 018, 0F8, 018, 0F8, 018, 018, 018, 018, 018, 018, 018, 018 ; db 036, 036, 036, 036, 036, 036, 036, 0F6, 036, 036, 036, 036, 036, 036, 036, 036 ; db 000, 000, 000, 000, 000, 000, 000, 0FE, 036, 036, 036, 036, 036, 036, 036, 036 ; db 000, 000, 000, 000, 000, 0F8, 018, 0F8, 018, 018, 018, 018, 018, 018, 018, 018 ; db 036, 036, 036, 036, 036, 0F6, 006, 0F6, 036, 036, 036, 036, 036, 036, 036, 036 ; db 036, 036, 036, 036, 036, 036, 036, 036, 036, 036, 036, 036, 036, 036, 036, 036 ; db 000, 000, 000, 000, 000, 0FE, 006, 0F6, 036, 036, 036, 036, 036, 036, 036, 036 ; db 036, 036, 036, 036, 036, 0F6, 006, 0FE, 000, 000, 000, 000, 000, 000, 000, 000 ; db 036, 036, 036, 036, 036, 036, 036, 0FE, 000, 000, 000, 000, 000, 000, 000, 000 ; db 018, 018, 018, 018, 018, 0F8, 018, 0F8, 000, 000, 000, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 000, 000, 0F8, 018, 018, 018, 018, 018, 018, 018, 018 ; db 018, 018, 018, 018, 018, 018, 018, 01F, 000, 000, 000, 000, 000, 000, 000, 000 ; db 018, 018, 018, 018, 018, 018, 018, 0FF, 000, 000, 000, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 000, 000, 0FF, 018, 018, 018, 018, 018, 018, 018, 018 ; db 018, 018, 018, 018, 018, 018, 018, 01F, 018, 018, 018, 018, 018, 018, 018, 018 ; db 000, 000, 000, 000, 000, 000, 000, 0FF, 000, 000, 000, 000, 000, 000, 000, 000 ; db 018, 018, 018, 018, 018, 018, 018, 0FF, 018, 018, 018, 018, 018, 018, 018, 018 ; db 018, 018, 018, 018, 018, 01F, 018, 01F, 018, 018, 018, 018, 018, 018, 018, 018 ; db 036, 036, 036, 036, 036, 036, 036, 037, 036, 036, 036, 036, 036, 036, 036, 036 ; db 036, 036, 036, 036, 036, 037, 030, 03F, 000, 000, 000, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 03F, 030, 037, 036, 036, 036, 036, 036, 036, 036, 036 ; db 036, 036, 036, 036, 036, 0F7, 000, 0FF, 000, 000, 000, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 0FF, 000, 0F7, 036, 036, 036, 036, 036, 036, 036, 036 ; db 036, 036, 036, 036, 036, 037, 030, 037, 036, 036, 036, 036, 036, 036, 036, 036 ; db 000, 000, 000, 000, 000, 0FF, 000, 0FF, 000, 000, 000, 000, 000, 000, 000, 000 ; db 036, 036, 036, 036, 036, 0F7, 000, 0F7, 036, 036, 036, 036, 036, 036, 036, 036 ; db 018, 018, 018, 018, 018, 0FF, 000, 0FF, 000, 000, 000, 000, 000, 000, 000, 000 ; db 036, 036, 036, 036, 036, 036, 036, 0FF, 000, 000, 000, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 0FF, 000, 0FF, 018, 018, 018, 018, 018, 018, 018, 018 ; db 000, 000, 000, 000, 000, 000, 000, 0FF, 036, 036, 036, 036, 036, 036, 036, 036 ; db 036, 036, 036, 036, 036, 036, 036, 03F, 000, 000, 000, 000, 000, 000, 000, 000 ; db 018, 018, 018, 018, 018, 01F, 018, 01F, 000, 000, 000, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 01F, 018, 01F, 018, 018, 018, 018, 018, 018, 018, 018 ; db 000, 000, 000, 000, 000, 000, 000, 03F, 036, 036, 036, 036, 036, 036, 036, 036 ; db 036, 036, 036, 036, 036, 036, 036, 0FF, 036, 036, 036, 036, 036, 036, 036, 036 ; db 018, 018, 018, 018, 018, 0FF, 018, 0FF, 018, 018, 018, 018, 018, 018, 018, 018 ; db 018, 018, 018, 018, 018, 018, 018, 0F8, 000, 000, 000, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 000, 000, 01F, 018, 018, 018, 018, 018, 018, 018, 018 ; db 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF ; db 000, 000, 000, 000, 000, 000, 000, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF ; db 0F0, 0F0, 0F0, 0F0, 0F0, 0F0, 0F0, 0F0, 0F0, 0F0, 0F0, 0F0, 0F0, 0F0, 0F0, 0F0 ; db 00F, 00F, 00F, 00F, 00F, 00F, 00F, 00F, 00F, 00F, 00F, 00F, 00F, 00F, 00F, 00F ; db 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 0FF, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 076, 0DC, 0D8, 0D8, 0D8, 0DC, 076, 000, 000, 000, 000 ; db 000, 000, 078, 0CC, 0CC, 0CC, 0D8, 0CC, 0C6, 0C6, 0C6, 0CC, 000, 000, 000, 000 ; db 000, 000, 0FE, 0C6, 0C6, 0C0, 0C0, 0C0, 0C0, 0C0, 0C0, 0C0, 000, 000, 000, 000 ; db 000, 000, 000, 000, 0FE, 06C, 06C, 06C, 06C, 06C, 06C, 06C, 000, 000, 000, 000 ; db 000, 000, 000, 0FE, 0C6, 060, 030, 018, 030, 060, 0C6, 0FE, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 07E, 0D8, 0D8, 0D8, 0D8, 0D8, 070, 000, 000, 000, 000 ; db 000, 000, 000, 000, 066, 066, 066, 066, 066, 07C, 060, 060, 0C0, 000, 000, 000 ; db 000, 000, 000, 000, 076, 0DC, 018, 018, 018, 018, 018, 018, 000, 000, 000, 000 ; db 000, 000, 000, 07E, 018, 03C, 066, 066, 066, 03C, 018, 07E, 000, 000, 000, 000 ; db 000, 000, 000, 038, 06C, 0C6, 0C6, 0FE, 0C6, 0C6, 06C, 038, 000, 000, 000, 000 ; db 000, 000, 038, 06C, 0C6, 0C6, 0C6, 06C, 06C, 06C, 06C, 0EE, 000, 000, 000, 000 ; db 000, 000, 01E, 030, 018, 00C, 03E, 066, 066, 066, 066, 03C, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 07E, 0DB, 0DB, 0DB, 07E, 000, 000, 000, 000, 000, 000 ; db 000, 000, 000, 003, 006, 07E, 0DB, 0DB, 0F3, 07E, 060, 0C0, 000, 000, 000, 000 ; db 000, 000, 01C, 030, 060, 060, 07C, 060, 060, 060, 030, 01C, 000, 000, 000, 000 ; db 000, 000, 000, 07C, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 0C6, 000, 000, 000, 000 ; db 000, 000, 000, 000, 0FE, 000, 000, 0FE, 000, 000, 0FE, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 018, 018, 07E, 018, 018, 000, 000, 0FF, 000, 000, 000, 000 ; db 000, 000, 000, 030, 018, 00C, 006, 00C, 018, 030, 000, 07E, 000, 000, 000, 000 ; db 000, 000, 000, 00C, 018, 030, 060, 030, 018, 00C, 000, 07E, 000, 000, 000, 000 ; db 000, 000, 00E, 01B, 01B, 018, 018, 018, 018, 018, 018, 018, 018, 018, 018, 018 ; db 018, 018, 018, 018, 018, 018, 018, 018, 0D8, 0D8, 0D8, 070, 000, 000, 000, 000 ; db 000, 000, 000, 000, 018, 018, 000, 07E, 000, 018, 018, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 076, 0DC, 000, 076, 0DC, 000, 000, 000, 000, 000, 000 ; db 000, 038, 06C, 06C, 038, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 000, 000, 018, 018, 000, 000, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 000, 000, 000, 018, 000, 000, 000, 000, 000, 000, 000 ; db 000, 00F, 00C, 00C, 00C, 00C, 00C, 0EC, 06C, 06C, 03C, 01C, 000, 000, 000, 000 ; db 000, 0D8, 06C, 06C, 06C, 06C, 06C, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; db 000, 070, 0D8, 030, 060, 0C8, 0F8, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 07C, 07C, 07C, 07C, 07C, 07C, 07C, 000, 000, 000, 000, 000 ; db 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000 ; .LIST ------- BitMap ---------------------------------- End ------------