Sunday, August 26, 2018

64 column text on a 256x192 graphics screen -> 6803

6803 code to print 64 column text on an MC-10 hi-res graphics screen.

Notes:
  1. This treats the screen as a 64 column x 24 row screen.  There is no terminal emulation but it could be added.
  2. Most of the optimizations were to the actual text rendering and scrolling code.
  3. Things like moving screen address calculation from the text rendering to the outer print code would reduce the size, and there is probably still room for some optimization.
  4. The scroll code pushes bytes to the screen because push requires 1 less clock cycle than pull.  The 6303 is exactly the opposite and the scroll would have to be changed for the greatest speed on it.
  5. This code is a version back, where the font data is still 7 bytes high, and the top byte is just erased. While this works fine for text, it does not suit graphics characters.  
  6. The font data consists of 2 tables, one for characters printed on the left side of the byte, and one for characters printed on the right side.  The first version packed the font into a much smaller space, but the bit shifting and masking made the code much slower.
  7. The entry point is just a demo, and use from an actual program may require changes.
  8. The beginnings of a 68hc11 version can be seen in the source code.
  9. As always, Blogger has messed up the code formatting.



;**************************************************
;* File: print64.6803
;**************************************************
;* Copyright (c) 2008-2015 James Diffendaffer
;**************************************************
;* Description:
;*  Emulates a 64 character by 24 line text display using 
;*  4 bit wide characters on a 256 * 192 graphics display.
;*  This version is for the Tandy MC-10 and 6803 CPU
;*
;*  Contains functions to print a string at the current screen location,
;*  print strings @ a specific screen location, line wrapping, scrolling,
;*  clear screen, the character generator and a font.
;*  Characters are stored with identical data in the left and right nibble
;*  to make rendering faster and several loops have been unrolled for speed.
;*  
;*  Loosly based on my VZ200 Z80 code's logic
;**************************************************
;* Version history
;*  Version  Date               Description
;*     2.06   Oct   6, 2015      Initial support for printing 2 characters at once when possible
;*     2.05   Oct   5, 2015      Added ability to invert text, cut some clock cycles from print, fixed a bug in scroll 
;*     2.04   Sept 30, 2015      Changed text rendering code to use EOR, saves 1 instruction per pixel height of character
;*     2.03   Sept 28, 2015      Added documentation,
;*     2.02,  Sept 26, 2015      Optimizations to print64, changed some comments
;*    2.01,  Sept  9, 2015      Optimized print routine, removed some unneeded code, corrected some comments
;*     2.00,  Sept  5, 2015      refactored for greater speed.    
;*                              Moved line wrap and scrolling to print function to match Z80 functionality
;*                               Font changed to use mirroed data in each nibble of the data to eliminate 
;*                               data shifting.
;*                               Older version information removed with refactoring.  
;**************************************************

;include MOTO.h
;defined for tasm.  tasm normally doesn't support motorola directives
.MSFIRST           ; Most Significant byte first

#define EQU     .EQU
#define ORG     .ORG
#define RMB     .BLOCK
#define FCB     .BYTE
#define FCC     .TEXT
#define FDB     .WORD
#define END  .END

#define equ     .EQU
#define org     .ORG
#define rmb     .BLOCK
#define fcb     .BYTE
#define fcc     .TEXT
#define fdb     .WORD
#define end  .END


;**************************************************
;MC-10 ROM entry vector addresses
;**************************************************
POLCAT equ  $FFDC  ; Read the keyboard
CHROUT equ  $FFDE  ; Output a character to the current device
CRSDON equ  $FFE0  ; Turn on the Cassette
BLKIN equ  $FFE2  ; Write a block of data to the cassette
BLKOUT equ  $FFE4  ; Read a block of data from the cassette
SNDOUT equ  $FFE6  ; Sound Output
WRTLDR equ  $FFE8  ; Write Leader
GIVABF equ  $FFEA  ; Convert 2 bytes to Basic
INTCNV equ  $FFEC  ; Convert BASIC to 2 bytes


;*************************************
; 6803 timer hardware
;*************************************
TCSR EQU  $0008  ; Timer Control Status Register
TIMER EQU  $0009  ; Counter
OCR  EQU  $000B  ; Output Compare Register
OCV  EQU  $4206  ; Output Compare interrupt Vector


;**************************************************
; MC-10 Graphics hardware definitions
;**************************************************
#define screen $4000  ; address of MC-10 screen memory
#define vdgport $BFFF  ; I/O address to set the VDG mode
#define RG6  %00111100 ; RG6 graphics mode bits
#define CSS  %01000000 ; color set select bit


;**************************************************
;* screen parameters
;*
;*  Define the graphics mode you are going to use as 1
;*  This is used to set up all the screen parameters used by
;*  the graphics routines so they will work in your 
;*  chosen mode. 
;**************************************************
#define GFX_RG6 1   ; Set the mode we will use here


;**************************************************
;* sets up the screen parameters based on define above
;**************************************************
#ifdef GFX_RG6      ; parameters for RG6
#define RGMODE 1
ScreenWidth  equ 256
ScreenHeight equ 192
BytesPerLine equ ((ScreenWidth)/8)
#endif

MAX_X   equ ScreenWidth-1
MAX_Y   equ ScreenHeight-1

;**************************************************
;page zero variables
;**************************************************
   org $00A0    ; start of Page 0 variables

temp0  rmb 2     ; temporary storage location.  used for transfering D to X or X to D etc...
temp1  rmb 2     ; temporary storage location.


;OE equ FGCOLOR+1
charptr  rmb 2
fscreen  rmb 2
fcount  rmb 1

;**************************************************
; location to temporarily hold the stack pointer
; when it is used as a pointer register
;**************************************************
stacktmp rmb 2

;**************************************************
; graphics text routine variables and macros
;**************************************************
row   rmb 1
col   rmb 1
BGColor  rmb 2
leftchar rmb 2
rightchar rmb 2

#DEFINE PRINTAT(loc,str) ldd loc \ ldx #str \ jsr print_at
#DEFINE PRINT(str) ldx #str \ jsr print
#DEFINE SetVDG(setting) ldaa #setting \ staa vdgport
;#DEFINE SetBGColor(setting) ldaa #setting \ staa BGColor \ staa BGColor+1

;**************************************************
;**************************************************
;**************************************************

START org $8000     ;where to store out program


;**************************************************
;* NAME: textdemo
;**************************************************
;* DESCRIPTION:
;*  a short program to demonstrate the use of 
;*  routines in the graphics library
;**************************************************
Textdemo:
 ; save the registers we will modify
; psha
; pshb
; pshx

; ldd  #$FFFF    ; row, col
 ldd  #$0000    ; row, col
 std  BGColor    ; set the background color
; jsr  invert_mem
 jsr  cls

; ldaa #RG6 ;+CSS   ; the graphics and color mode
; staa vdgport     ; set it

 SetVDG(RG6)     ; set the graphics mode
 ldd  #0
 std  row     ; clear row and column, they are consecutive bytes on the direct page

; 64 character/line demo, prints entire character set
 ldx  #String    ; point to our string buffer
 ldaa #' '    ; the first character in the font
lllm:
 staa ,x     ; save it to the string
 inx       ; next string address
 inca      ; next character
 cmpa #'~'+1    ; are we past the last character in the font?
 bne  lllm
 ldaa #0     ; zero terminate the string
 staa ,x
start:
 PRINT(String)
 bra   start

 rts


;**************************************************
;* NAME: cls
;**************************************************
;* DESCRIPTION:
;*  Clears the screen memory to zeros
;*
;* The stack pointer is used as 2nd pointer register
;* but interrupts must be disabled to do this.
;* We could just use X as a pointer but PSHX is faster
;* than the alternative code
;**************************************************
cls
 pshx
 pshb
; psha
 
 tsx       ; copy stack pointer to x
 stx stacktmp
; wai       ;<- uncomment if you want to make sure cls takes place between interrupts
 sei       ;disable interrupts
 lds #screen+(BytesPerLine*(ScreenHeight))-1 ;last screen address.
; txs       ;point S to screen top
 ldx  BGColor    ;clear the screen to the background color
 ldab #((BytesPerLine*(ScreenHeight))/32)  ;number of loops to clear screen
_clsloop:
 pshx      ; Partially unrolled loop clears at least an entire screen row each pass
 pshx      ;  lets us use an 8 bit loop counter even in RG6
 pshx      ;  so we don't have to dec and test LSB and MSB of loop counter (there is no DECD instruction)
 pshx      ;  32 bytes / pass = first power of 2 with loop counter below 256 (fits in 1 byte)
 pshx      ; Fewer loops also requires fewer loop instructions to execute
 pshx      ;  and saves a lot of clock cycles.
 pshx
 pshx
 pshx
 pshx
 pshx
 pshx
 pshx
 pshx
 pshx
 pshx
 decb      ;decrement loop counter
 bne _clsloop    ;branch until it equals zero
 ldx stacktmp
 txs       ;restore the stack pointer
 cli       ;enable interrupts

; pula
 pulb
 pulx

 rts


;**************************************************
;* Description:
;*  scroll the 24 line display
;* Must reserve 4 bytes of RAM below screen in case of interrupt on 
;**************************************************
;68hc11 version
;#define MScroll(A) ldx A+30,y \ pshx \ ldx A+28,y \ pshx \ ldx A+26,y \ pshx \ ldx A+24,y \ pshx \ ldx A+22,y \ pshx \ ldx A+20,y \ pshx \ ldx A+18,y \ pshx \ ldx A+16,y \ pshx \ ldx A+14,y \ pshx \ ldx A+12,y \ pshx \ ldx A+10,y \ pshx \ ldx A+8,y \ pshx \ ldx A+6,y \ pshx \ ldx A+4,y \ pshx \ ldx A+2,y \ pshx \ ldx A,y \ pshx

#define MScroll(A) ldd A+30,x \ pshb \ psha \ ldd A+28,x \ pshb \ psha \ ldd A+26,x \ pshb \ psha \ ldd A+24,x \ pshb \ psha \ ldd A+22,x \ pshb \ psha \ ldd A+20,x \ pshb \ psha \ ldd A+18,x \ pshb \ psha \ ldd A+16,x \ pshb \ psha \ ldd A+14,x \ pshb \ psha \ ldd A+12,x \ pshb \ psha \ ldd A+10,x \ pshb \ psha \ ldd A+8,x \ pshb \ psha \ ldd A+6,x \ pshb \ psha \ ldd A+4,x \ pshb \ psha \ ldd A+2,x \ pshb \ psha \ ldd A,x \ pshb \ psha
#define MScrollB(A) ldd A+30,x \ pshb \ psha \ ldd A+28,x \ pshb \ psha \ ldd A+26,x \ pshb \ psha \ ldd A+24,x \ pshb \ psha \ ldd A+22,x \ pshb \ psha \ ldd A+20,x \ pshb \ psha \ ldd A+18,x \ pshb \ psha \ ldd A+16,x \ pshb \ psha \ ldd A+14,x \ pshb \ psha \ ldd A+12,x \ pshb \ psha \ ldd A+10,x \ pshb \ psha \ ldd A+8,x \ pshb \ psha \ ldd A+6,x \ pshb \ psha \ ldd A+4,x \ pshb \ psha \ ldd A+2,x \ sei \ pshb \ psha \ ldd A,x \ pshb \ psha
#define ClLine    pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx
#define ClLine2   pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ pshx \ sei \ pshx \ pshx \ pshx \ pshx

.MODULE Scroll
scroll:
 ldaa #23
; ldaa #15
 staa temp0     ; loop counter
 ldx  #screen+(BytesPerLine*8) ; 
 sts  stacktmp     ; save the stack pointer
; lds  #screen+(BytesPerLine*8)-1 ; character line +1
 txs
 ;the scroll section
_scrolla:
 MScroll(224)     ; for scrolling all lines instead of erasing one.
 MScroll(192)
 MScroll(160)
 MScroll(128)
 MScroll(96)
 MScroll(64)
 MScroll(32)
 MScrollB(0)
 
 dec  temp0     ; decrement our loop counter
 ble  nxtscroll    ; exit if we are done

 ldab #255     ; adjust x for the next text row
 abx
 inx
 txs

 cli

  jmp  _scrolla    ; keep going until we've scrolled every text row

nxtscroll: 
 ;clear the bottom charater row
 lds  #screen+(BytesPerLine*(ScreenHeight))-1 ;last screen address.
 cli
 ldx  BGColor     ; clear x for use in the macro
 ClLine       ; clear the top line of the text row
 ClLine       ; next one down
 ClLine       ; and so on
 ClLine
 ClLine
 ClLine
 ClLine
 ClLine2       ; last one, use a different macro to disable interrupts for the last 8 bytes
         ; we don't want an interrupt to overwrite memory below this line

 ;restore stack & interrupts
 lds stacktmp    ; restore the stack pointer
 cli       ; enable interrupts

 rts       ; done

;**************************************************
;* invert_mem
;**************************************************
;*  nope length contains the length
;**************************************************
invert_mem:
 ldx  #leftfont
nxtaddr:
 ldd  ,x       ; get original byte
 eora #$FF      ; invert it
 eorb #$FF      ; invert it
 std  ,x       ; write it back
 inx
 inx
 cpx  #String
 bne  nxtaddr
 
 rts

 
;**************************************************
;* print_at
;**************************************************
;* Prints a string at a screen location
;* works similar to print@ in BASIC
;*  d contains @ location
;*  x contains string pointer
;* falls through to _print
;**************************************************
;.MODULE Print_AT
print_at:
 stab temp0    ;save it
 andb #(BytesPerLine*2)-1 ;111111 ;mask of row bits
 stab col     ;save the column
 ldab temp0    ;restore it
 andb #254-(BytesPerLine*2) ;%11000000 ;mask off column bits
 lsld      ;rotate bits into a
 lsld
 staa row     ;save row

 
;**************************************************
;* print
;**************************************************
;* Prints a zero terminated string at the current x,y location
;*  x contains the string pointer
;**************************************************
.MODULE Print
print:
 ldaa col
 lsra
 bcs  prn1    ; print single char if we are on the right nibble
 
prn4:       ; see if we can print 2 characters at once
 ldd  ,x     ; get next 2 characters from the string
 cmpa #0
 beq  _printexit   ; exit if first char is a string terminator

 cmpb #0
 beq  prn2    ; print single char if 2nd char a string terminator

 ; print 2 characters
 pshx
 jsr  print_642
 pulx
 ; inc string pointer and column an extra time since we printed 2 characters
 ; since we know we were on a byte boundary we know we won't be going more than one column past the end of the line
 inx
 inc  col
 bra  prn3    ; continue with normal return from printing

prn1:
 ldaa ,x
 cmpa #0
 beq  _printexit   ; exit if it's a zero
prn2:
 pshx
 jsr  print_64   ; print the character
 pulx      ; restore x
prn3:
 inx       ; increment the string pointer x
 ;update column, row, and scroll when needed
 inc  col     ; next column
 ldaa col
 cmpa #(BytesPerLine*2) ; 64 chsrs / line (0-63)
 bne  prn4    ; is column past the end of a line?

 clr  col     ; set column to zero
 inc  row     ; increment row
 ldaa row
 cmpa #(ScreenHeight/8) ; 24 lines (0-23)
; cmpa #16     ; 16 lines (0-23) *for debugging*
 bne  prn4
 
 dec  row
 pshx ; save x
 jsr  scroll    ; scroll the screen
 pulx      ; restore x
 
 bra  prn4    ; keep printing
_printexit:      ; we are done
 rts
 
 
;**************************************************
;* NAME: scroll
 
;**************************************************
; NAME: print_64
;**************************************************
;* Description:
;*  64 Column text display driver
;*  Routine does not print at pixel X,Y but
;*  prints at a character position.
;*  Once a string printing routine is written, 
;*  some of the code may be moved to that.
;**************************************************
.MODULE Print_64
print_64:
 ldab #7     ; 7 bytes per character
 mul       ; multiply them
 std  temp0    ; save font offset

 ldd  row     ; screen offset
 lsrb
 bcs  rightnibble

;**************************************************
;* left nibble
;**************************************************
 addd #screen    ; 7 row font data, top line of character is always blank so skip it
 std  SCRNl+1    ; transfer to x for our screen pointer
SCRNl:
 ldx  #0000    ; self modifying code

 ldd  #leftfont-225
 addd temp0
 std  CHARPTRl+1   ; save to character pointer

 sts  stacktmp1+1   ; save the stack pointer
 sei       ; disable interrupts

CHARPTRl:      ; for self modifying code
 lds  #0000    ; point the stack to the current character
; lds  charptr    ; point the stack to the current character

;start printing
 ldaa BGColor    ; load background color to A and write it to the screen
 staa ,x     ; the top row of the font is always blank
 
 pula      ; get byte of font and point to next font data
 eora 32,x    ; read byte at destination
; anda #%11110000   ; mask off unused half
; eora 32,x
 staa 32,x

 pula      ; get byte of font and point to next font data
 eora 64,x    ; read byte at destination
; anda #%11110000   ; mask off unused half
; eora 64,x
 staa 64,x

 pula      ; get byte of font and point to next font data
 eora 96,x    ; read byte at destination
; anda #%11110000   ; mask off unused half
; eora 96,x
 staa 96,x

 pula      ; get byte of font and point to next font data
 eora 128,x    ; read byte at destination
; anda #%11110000   ; mask off unused half
; eora 128,x
 staa 128,x

 pula      ; get byte of font and point to next font data
 eora 160,x    ; read byte at destination
; anda #%11110000   ; mask off unused half
; eora 160,x
 staa 160,x

 pula      ; get byte of font and point to next font data
 eora 192,x    ; read byte at destination
; anda #%11110000   ; mask off unused half
; eora 192,x
 staa 192,x

 pula      ; get byte of font and point to next font data
 eora 224,x    ; read byte at destination
; anda #%11110000   ; mask off unused half
; eora 224,x
 staa 224,x

 ;restore stack pointer and interrupts
stacktmp1:
 lds  #0000    ; restore the stack pointer
 cli       ; enable interrupts

 rts       ; return
 

;**************************************************
;* right nibble
;**************************************************
rightnibble:
 addd #screen    ; 7 row font data, top line of character is always blank so skip it
 std  SCRNr+1    ; transfer to x for our screen pointer
SCRNr:
 ldx  #0000    ; self modifying code

 ldd  #rightfont-225
 addd temp0
 std  CHARPTRr+1   ; save to character pointer

 sts  stacktmp   ; save the stack pointer
 sei       ; disable interrupts

CHARPTRr:      ; for self modifying code
 lds  #0000    ; point the stack to the current character
; lds  charptr    ; point the stack to the current character

;start printing
 ldaa BGColor    ; load background color to A and write it to the screen
 staa ,x     ; the top row of the font is always blank

 pula      ; get byte of font and point to next font data
 eora 32,x    ; read byte at destination
; anda #001111   ; mask off unused half
; eora 32,x
 staa 32,x

 pula      ; get byte of font and point to next font data
 eora 64,x    ; read byte at destination
; anda #001111   ; mask off unused half
; eora 64,x
 staa 64,x

 pula      ; get byte of font and point to next font data
 eora 96,x    ; read byte at destination
; anda #001111   ; mask off unused half
; eora 96,x
 staa 96,x

 pula      ; get byte of font and point to next font data
 eora 128,x    ; read byte at destination
; anda #001111   ; mask off unused half
; eora 128,x
 staa 128,x

 pula      ; get byte of font and point to next font data
 eora 160,x    ; read byte at destination
; anda #001111   ; mask off unused half
; eora 160,x
 staa 160,x

 pula      ; get byte of font and point to next font data
 eora 192,x    ; read byte at destination
; anda #001111   ; mask off unused half
; eora 192,x
 staa 192,x

 pula      ; get byte of font and point to next font data
 eora 224,x    ; read byte at destination
; anda #001111   ; mask off unused half
; eora 224,x
 staa 224,x

 ;restore stack pointer and interrupts
 lds  stacktmp   ; restore the stack pointer
 cli       ; enable interrupts

 rts       ; return
 

;**************************************************
; write two characters at once
;**************************************************
print_642:
; ldaa ,x
 ldab #7     ; 7 bytes per character
 mul       ; multiply them
 addd #leftfont-225  ; base address of font, -224 to subtract ' ' from char, -1 to adjust for using stack as a pointer
 std  leftchar   ; save to character pointer
 
 ldaa 1,x
 ldab #7     ; 7 bytes per character
 mul       ; multiply them
 addd #rightfont-224  ; base address of font, -224 to subtract ' ' from char
 std  rightchar

 ldd  row     ; put the row to the MSB, col in LSB
 lsrb
 addd #screen    ; 7 row font data, top line of character is always blank so skip it
 std  fscreen    ; transfer to x for our screen pointer

 sts  stacktmp   ; save the stack pointer
; sei       ; disable interrupts
; lds  leftchar   ; point the stack to the current character

twochar:
 ldaa BGColor    ; load background color to A and write it to the screen
 ldx  fscreen
 staa ,x     ; the top row of the font is always blank

 sei       ; disable interrupts
 lds  leftchar   ; point the stack to the current character
 
 pula      ; get byte of first character and point to next byte data
 ldx  rightchar   ; point to right char
 eora 0,x     ; add the right character to the byte
 ldx  fscreen    ; point to screen 
 staa 32,x

 pula      ; get byte of font and point to next font data
 ldx  rightchar   ; point to right char
 eora 1,x     ; add the right character to the byte
 ldx  fscreen    ; point to screen 
 staa 64,x

 pula      ; get byte of font and point to next font data
 ldx  rightchar   ; point to right char
 eora 2,x     ; add the right character to the byte
 ldx  fscreen    ; point to screen 
 staa 96,x

 pula      ; get byte of font and point to next font data
 ldx  rightchar   ; point to right char
 eora 3,x     ; add the right character to the byte
 ldx  fscreen    ; point to screen 
 staa 128,x

 pula      ; get byte of font and point to next font data
 ldx  rightchar   ; point to right char
 eora 4,x     ; add the right character to the byte
 ldx  fscreen    ; point to screen 
 staa 160,x

 pula      ; get byte of font and point to next font data
 ldx  rightchar   ; point to right char
 eora 5,x     ; add the right character to the byte
 ldx  fscreen    ; point to screen 
 staa 192,x

 pula      ; get byte of font and point to next font data
 ldx  rightchar   ; point to right char
 eora 6,x     ; add the right character to the byte
 ldx  fscreen    ; point to screen 
 staa 224,x

 ;restore stack pointer and interrupts
 lds  stacktmp   ; restore the stack pointer
 cli       ; enable interrupts

 rts       ; return

 
;**************************************************
; HALF WIDTH 4x8 FONT
; Top row is always zero and not stored (336 bytes)
; characters are 4 bits wide and 7 bits high 
; (the top row is always blank)
;**************************************************
.MODULE Font
leftfont:
 fcb $00, $00, $00, $00, $00, $00, $00 ; 
 fcb $20, $20, $20, $20, $00, $20, $00 ;!
 fcb $50, $50, $00, $00, $00, $00, $00 ;"
 fcb $20, $70, $20, $20, $70, $20, $00 ;#
 fcb $20, $70, $60, $30, $70, $20, $00 ;$
 fcb $50, $10, $20, $20, $40, $50, $00 ;%
 fcb $20, $40, $30, $50, $50, $30, $00 ;&
 fcb $20, $20, $00, $00, $00, $00, $00 ;'
 fcb $10, $20, $40, $40, $40, $20, $10 ;(
 fcb $40, $20, $10, $10, $10, $20, $40 ;)
 fcb $20, $70, $20, $50, $00, $00, $00 ;*
 fcb $00, $00, $20, $70, $20, $00, $00 ;+
 fcb $00, $00, $00, $00, $00, $20, $20 ;,
 fcb $00, $00, $00, $70, $00, $00, $00 ;-
 fcb $00, $00, $00, $00, $00, $10, $00 ;.
 fcb $10, $10, $20, $20, $40, $40, $00 ;/
 fcb $20, $50, $50, $50, $50, $20, $00 ;0
 fcb $20, $60, $20, $20, $20, $70, $00 ;1
 fcb $20, $50, $10, $20, $40, $70, $00 ;2
 fcb $70, $10, $20, $10, $50, $20, $00 ;3
 fcb $50, $50, $50, $70, $10, $10, $00 ;4
 fcb $70, $40, $60, $10, $50, $20, $00 ;5
 fcb $10, $20, $60, $50, $50, $20, $00 ;6
 fcb $70, $10, $10, $20, $20, $20, $00 ;7
 fcb $20, $50, $20, $50, $50, $20, $00 ;8
 fcb $20, $50, $50, $30, $20, $40, $00 ;9
 fcb $00, $00, $20, $00, $00, $20, $00 ;:
 fcb $00, $00, $20, $00, $00, $20, $20 ;;
 fcb $00, $10, $20, $40, $20, $10, $00 ;<
 fcb $00, $00, $70, $00, $70, $00, $00 ;=
 fcb $00, $40, $20, $10, $20, $40, $00 ;>
 fcb $20, $50, $10, $20, $00, $20, $00 ;?
 fcb $20, $50, $70, $70, $40, $30, $00 ;@
 fcb $30, $50, $50, $70, $50, $50, $00 ;A
 fcb $60, $50, $60, $50, $50, $60, $00 ;B
 fcb $30, $40, $40, $40, $40, $30, $00 ;C
 fcb $60, $50, $50, $50, $50, $60, $00 ;D
 fcb $70, $40, $60, $40, $40, $70, $00 ;E
 fcb $70, $40, $60, $40, $40, $40, $00 ;F
 fcb $30, $40, $40, $50, $50, $30, $00 ;G
 fcb $50, $50, $70, $50, $50, $50, $00 ;H
 fcb $70, $20, $20, $20, $20, $70, $00 ;I
 fcb $30, $10, $10, $50, $50, $20, $00 ;J
 fcb $50, $50, $60, $50, $50, $50, $00 ;K
 fcb $40, $40, $40, $40, $40, $70, $00 ;L
 fcb $50, $70, $50, $50, $50, $50, $00 ;M
 fcb $60, $50, $50, $50, $50, $50, $00 ;N
 fcb $20, $50, $50, $50, $50, $20, $00 ;O
 fcb $60, $50, $50, $60, $40, $40, $00 ;P
 fcb $20, $50, $50, $50, $50, $30, $00 ;Q
 fcb $60, $50, $50, $60, $50, $50, $00 ;R
 fcb $30, $40, $20, $10, $50, $20, $00 ;S
 fcb $70, $20, $20, $20, $20, $20, $00 ;T
 fcb $50, $50, $50, $50, $50, $20, $00 ;U
 fcb $50, $50, $50, $50, $20, $20, $00 ;V
 fcb $50, $50, $50, $50, $70, $50, $00 ;W
 fcb $50, $50, $20, $20, $50, $50, $00 ;X
 fcb $50, $50, $50, $20, $20, $20, $00 ;Y
 fcb $70, $10, $20, $20, $40, $70, $00 ;Z
 fcb $30, $20, $20, $20, $20, $20, $30 ;[
 fcb $40, $40, $20, $20, $10, $10, $00 ;\
 fcb $60, $20, $20, $20, $20, $20, $60 ;]
 fcb $20, $50, $00, $00, $00, $00, $00 ;^
 fcb $00, $00, $00, $00, $00, $00, $F0 ;_
 fcb $20, $10, $00, $00, $00, $00, $00 
 fcb $00, $00, $30, $50, $50, $30, $00 ;a
 fcb $40, $40, $60, $50, $50, $60, $00 ;b
 fcb $00, $00, $30, $40, $40, $30, $00 ;c
 fcb $10, $10, $30, $50, $50, $30, $00 ;d
 fcb $00, $00, $20, $50, $60, $30, $00 ;e
 fcb $10, $20, $70, $20, $20, $40, $00 ;f
 fcb $00, $00, $30, $50, $50, $30, $60 ;g
 fcb $40, $40, $60, $50, $50, $50, $00 ;h
 fcb $20, $00, $60, $20, $20, $70, $00 ;i
 fcb $10, $00, $30, $10, $10, $50, $20 ;j
 fcb $40, $40, $50, $60, $50, $50, $00 ;k
 fcb $60, $20, $20, $20, $20, $70, $00 ;l
 fcb $00, $00, $50, $70, $50, $50, $00 ;m
 fcb $00, $00, $60, $50, $50, $50, $00 ;n
 fcb $00, $00, $20, $50, $50, $20, $00 ;o
 fcb $00, $00, $60, $50, $50, $60, $40 ;p
 fcb $00, $00, $30, $50, $50, $30, $10 ;q
 fcb $00, $00, $50, $60, $40, $40, $00 ;r
 fcb $00, $00, $30, $60, $30, $60, $00 ;s
 fcb $00, $20, $70, $20, $20, $10, $00 ;t
 fcb $00, $00, $50, $50, $50, $20, $00 ;u
 fcb $00, $00, $50, $50, $20, $20, $00 ;v
 fcb $00, $00, $50, $50, $70, $50, $00 ;w
 fcb $00, $00, $50, $20, $20, $50, $00 ;x
 fcb $00, $00, $50, $50, $50, $30, $60 ;y
 fcb $00, $00, $70, $30, $60, $70, $00 ;z
 fcb $10, $20, $20, $40, $20, $20, $10 ;{
 fcb $20, $20, $20, $20, $20, $20, $00 ;|
 fcb $40, $20, $20, $10, $20, $20, $40 ;}
 fcb $50, $a0, $00, $00, $00, $00, $00 ;~
 fcb $60, $90, $60, $40, $60, $90, $60 
 
rightfont:
 fcb $00, $00, $00, $00, $00, $00, $00 ; 
 fcb $02, $02, $02, $02, $00, $02, $00 ;!
 fcb $05, $05, $00, $00, $00, $00, $00 ;"
 fcb $02, $07, $02, $02, $07, $02, $00 ;#
 fcb $02, $07, $06, $03, $07, $02, $00 ;$
 fcb $05, $01, $02, $02, $04, $05, $00 ;%
 fcb $02, $04, $03, $05, $05, $03, $00 ;&
 fcb $02, $02, $00, $00, $00, $00, $00 ;'
 fcb $01, $02, $04, $04, $04, $02, $01 ;(
 fcb $04, $02, $01, $01, $01, $02, $04 ;)
 fcb $02, $07, $02, $05, $00, $00, $00 ;*
 fcb $00, $00, $02, $07, $02, $00, $00 ;+
 fcb $00, $00, $00, $00, $00, $02, $02 ;,
 fcb $00, $00, $00, $07, $00, $00, $00 ;-
 fcb $00, $00, $00, $00, $00, $01, $00 ;.
 fcb $01, $01, $02, $02, $04, $04, $00 ;/
 fcb $02, $05, $05, $05, $05, $02, $00 ;0
 fcb $02, $06, $02, $02, $02, $07, $00 ;1
 fcb $02, $05, $01, $02, $04, $07, $00 ;2
 fcb $07, $01, $02, $01, $05, $02, $00 ;3
 fcb $05, $05, $05, $07, $01, $01, $00 ;4
 fcb $07, $04, $06, $01, $05, $02, $00 ;5
 fcb $01, $02, $06, $05, $05, $02, $00 ;6
 fcb $07, $01, $01, $02, $02, $02, $00 ;7
 fcb $02, $05, $02, $05, $05, $02, $00 ;8
 fcb $02, $05, $05, $03, $02, $04, $00 ;9
 fcb $00, $00, $02, $00, $00, $02, $00 ;:
 fcb $00, $00, $02, $00, $00, $02, $02 ;;
 fcb $00, $01, $02, $04, $02, $01, $00 ;<
 fcb $00, $00, $07, $00, $07, $00, $00 ;=
 fcb $00, $04, $02, $01, $02, $04, $00 ;>
 fcb $02, $05, $01, $02, $00, $02, $00 ;?
 fcb $02, $05, $07, $07, $04, $03, $00 ;@
 fcb $03, $05, $05, $07, $05, $05, $00 ;A
 fcb $06, $05, $06, $05, $05, $06, $00 ;B
 fcb $03, $04, $04, $04, $04, $03, $00 ;C
 fcb $06, $05, $05, $05, $05, $06, $00 ;D
 fcb $07, $04, $06, $04, $04, $07, $00 ;E
 fcb $07, $04, $06, $04, $04, $04, $00 ;F
 fcb $03, $04, $04, $05, $05, $03, $00 ;G
 fcb $05, $05, $07, $05, $05, $05, $00 ;H
 fcb $07, $02, $02, $02, $02, $07, $00 ;I
 fcb $03, $01, $01, $05, $05, $02, $00 ;J
 fcb $05, $05, $06, $05, $05, $05, $00 ;K
 fcb $04, $04, $04, $04, $04, $07, $00 ;L
 fcb $05, $07, $05, $05, $05, $05, $00 ;M
 fcb $06, $05, $05, $05, $05, $05, $00 ;N
 fcb $02, $05, $05, $05, $05, $02, $00 ;O
 fcb $06, $05, $05, $06, $04, $04, $00 ;P
 fcb $02, $05, $05, $05, $05, $03, $00 ;Q
 fcb $06, $05, $05, $06, $05, $05, $00 ;R
 fcb $03, $04, $02, $01, $05, $02, $00 ;S
 fcb $07, $02, $02, $02, $02, $02, $00 ;T
 fcb $05, $05, $05, $05, $05, $02, $00 ;U
 fcb $05, $05, $05, $05, $02, $02, $00 ;V
 fcb $05, $05, $05, $05, $07, $05, $00 ;W
 fcb $05, $05, $02, $02, $05, $05, $00 ;X
 fcb $05, $05, $05, $02, $02, $02, $00 ;Y
 fcb $07, $01, $02, $02, $04, $07, $00 ;Z
 fcb $03, $02, $02, $02, $02, $02, $03 ;[
 fcb $04, $04, $02, $02, $01, $01, $00 ;\
 fcb $06, $02, $02, $02, $02, $02, $06 ;]
 fcb $02, $05, $00, $00, $00, $00, $00 ;^
 fcb $00, $00, $00, $00, $00, $00, $0f ;_
 fcb $02, $01, $00, $00, $00, $00, $00 
 fcb $00, $00, $03, $05, $05, $03, $00 ;a
 fcb $04, $04, $06, $05, $05, $06, $00 ;b
 fcb $00, $00, $03, $04, $04, $03, $00 ;c
 fcb $01, $01, $03, $05, $05, $03, $00 ;d
 fcb $00, $00, $02, $05, $06, $03, $00 ;e
 fcb $01, $02, $07, $02, $02, $04, $00 ;f
 fcb $00, $00, $03, $05, $05, $03, $06 ;g
 fcb $04, $04, $06, $05, $05, $05, $00 ;h
 fcb $02, $00, $06, $02, $02, $07, $00 ;i
 fcb $01, $00, $03, $01, $01, $05, $02 ;j
 fcb $04, $04, $05, $06, $05, $05, $00 ;k
 fcb $06, $02, $02, $02, $02, $07, $00 ;l
 fcb $00, $00, $05, $07, $05, $05, $00 ;m
 fcb $00, $00, $06, $05, $05, $05, $00 ;n
 fcb $00, $00, $02, $05, $05, $02, $00 ;o
 fcb $00, $00, $06, $05, $05, $06, $04 ;p
 fcb $00, $00, $03, $05, $05, $03, $01 ;q
 fcb $00, $00, $05, $06, $04, $04, $00 ;r
 fcb $00, $00, $03, $06, $03, $06, $00 ;s
 fcb $00, $02, $07, $02, $02, $01, $00 ;t
 fcb $00, $00, $05, $05, $05, $02, $00 ;u
 fcb $00, $00, $05, $05, $02, $02, $00 ;v
 fcb $00, $00, $05, $05, $07, $05, $00 ;w
 fcb $00, $00, $05, $02, $02, $05, $00 ;x
 fcb $00, $00, $05, $05, $05, $03, $06 ;y
 fcb $00, $00, $07, $03, $06, $07, $00 ;z
 fcb $01, $02, $02, $04, $02, $02, $01 ;{
 fcb $02, $02, $02, $02, $02, $02, $00 ;|
 fcb $04, $02, $02, $01, $02, $02, $04 ;}
 fcb $05, $0a, $00, $00, $00, $00, $00 ;~
 fcb $06, $09, $06, $04, $06, $09, $06 
String: rmb 256

 end

No comments:

Post a Comment