Browse Source

updated documentation

Zeda Thomas 4 years ago
parent
commit
89c3e2ec02

+ 33 - 0
docs/data-types.md

@@ -0,0 +1,33 @@
+# Data Types
+
+```
+   name     You use:
+00=Real         log(    Real Format
+01=List         A       Real Format
+02=Matrix       B       Real Format
+03=EQU          C       Symbol Var
+04=String       D       Symbol Var
+05=Program      E       Named Var
+06=ProtProg     [       Named Var
+07=Picture      ]       Symbol Var
+08=GDB          {       Symbol Var
+09=Unknown      }       Not Supported
+10=UnknownEqu   J       Not Supported
+11=New EQU      K       Not Supported
+12=Complex      L       Real Format
+13=Complex List M       Real Format
+14=Undefined    N       Not Supported
+15=Window       O       Not Supported
+16=ZSto         0       Not Supported
+17=Table Range  1       Not Supported
+18=LCD          2       Not Supported
+19=BackUp       3       Not Supported
+20=App          4       Not Supported
+21=Appvar       5       Named Var
+22=TempProg     6       Named Var
+23=Group        7       Named Var   this can mess stuff up unless you *really* know what you are doing.
+```
+
+Symbol Vars are compatible with each other.
+Named Vars are compatible with each other.
+Real Format variables are a special format generally not supported by Grammer.

+ 126 - 0
docs/drawing.md

@@ -0,0 +1,126 @@
+<h1>Table of Contents</h1>
+
+<!-- MDTOC maxdepth:6 firsth1:2 numbering:0 flatten:0 bullets:1 updateOnSave:1 -->
+
+- [Graphics Buffers](#graphics-buffers)   
+- [Grayscale](#grayscale)   
+- [Sprites](#sprites)   
+   - [Sprite Data](#sprite-data)   
+   - [Sprite Logic](#sprite-logic)   
+   - [Displaying Sprites](#displaying-sprites)   
+
+<!-- /MDTOC -->
+# Drawing
+
+Drawing in Grammer has a few similarities to TI-BASIC, but not many. In Grammer, you'll need a lower-level understanding of graphics, and that is what we'll aim to teach here. To understand, a primary difference is that Grammer uses pixel coordinates, like the BASIC `Pxl-*` commands.
+
+The first thing you need to know is that drawing is done on "graphics buffers" before it is displayed on the LCD. This is true for both BASIC and Grammer. The difference is that in Grammer you have to manually issue a command to draw from the buffer to the LCD, and in BASIC it is automatic. This may sound annoying, but it's actually great because it lets you perform batch drawing operations before displaying. It makes for much smoother and faster graphics. We'll discuss buffers in more detail later, but for now here is an example.
+
+Now, to the actual drawing!
+In all cases, (0,0) is the upper left corner of the screen.
+
+```
+:.0:Return
+:ClrDraw
+:Repeat getKey(15     ;Loop until [Clear] is pressed.
+:randInt(0,96→X
+:randInt(0,64→Y
+:randInt(0,64→R
+:Circle(Y,X,R,1       ;Draws a circle with a black outline with radius R, centered at (Y,X)
+:DispGraph            ;Now that we've drawn to the buffer, display it to the LCD
+:End
+:Stop
+```
+![Animated Circle Example](https://i.imgur.com/JGllOAw.gif)
+
+## Graphics Buffers
+
+Graphics buffers are 768 byte areas of memory (normally RAM) that store pixel data.
+Pixel data is not shown on the LCD until you issue a `DispGraph` command. This means you can modify it however you like before showing the contents. For those who want to do *really* low level modifications, these buffers are stored such that each byte represents 8 pixels, where bit 7 corresponds to the left-most bit, and each twelve bytes forms a 96-pixel row, starting from the top of the screen.
+
+There are various reasons one might want to draw to some other buffer, or display some other buffer (especially in grayscale drawing). Grammer reserves two buffers for graphics, the primary being the graphscreen buffer used by the OS, located at `0x9340`. The other is what is called `AppBackUpScreen` located at `0x9872`. You don't have to memorize these addresses, you can use `G-T` and `G-T'`, respectively.
+
+Most graphics routines allow you to provide an optional argument designating a graphics buffer to draw to. However, you can also set a default buffer with the `Disp ` function. For example, `Disp π9872` or `Disp G-T'`.
+Now, whenever you draw or update the LCD, that is the buffer that will be
+used. This means you can preserve the graph screen.
+
+## Grayscale
+Grammer has built-in grayscale support. Since the calculator is monochrome, this means alternating colors at the right frequency to achieve a gray-looking pixel. Knowing how buffers work, you can give this a try. First, you need two buffers-- a back buffer and a front buffer. Define these using `Disp °` and `Disp '`, respectively (both found in the Angle menu). For example, to add the back buffer, use `Disp °π9872` and now whenever you use `DispGraph`, it will update one cycle of gray. Because the LCD does not support grayscale naturally, you will need to update the LCD often and regularly.
+
+A pixel is seen as gray if it is ON in one of the buffers, but OFF in the other
+buffer. If a pixel is on in the front buffer, it will appear darker. Here is
+an example program that draws in grayscale:
+```
+:.0:
+:G-T'→Z      ;G-T' is the pointer to 9872h, appBackUpScreen
+:Disp °Z
+:ClrDraw
+:ClrDrawZ
+:0→X→Y
+:Repeat getKey(15
+:Pxl-Change(Y,X       ;Just drawing the cursor
+:Pxl-Change(Y,X,Z     ;Pixel changing it on both buffers
+:DispGraph
+:Pxl-Change(Y,X
+:Pxl-Change(Y,X,Z
+:If getKey(54
+:Pxl-On(Y,X,Z
+:If getKey(9
+:Pxl-On(Y,X
+:If getKey(54:+getKey(56  ;If [2nd] or [Del]
+:Pxl-Off(Y,X
+:If getKey(9:+getkey(56   ;If [Enter] or [Del]
+:Pxl-Off(Y,X,Z
+:X+getKey(3:-getKey(2
+:If <96
+:→X
+:Y+getKey(1
+:-getKey(4:If <64
+:→Y
+:End
+:Stop
+```
+
+## Sprites
+Using sprites is a pretty advanced technique, so don't expect to understand everything here. Sprites are pretty much mini pictures. They are a quick way to get detailed objects that move around making them a powerful graphics tool. In Grammer, the main sprite commands are `Pt-On(` and `Pt-Off(` and both have differences and advantages over the other.
+
+### Sprite Data
+
+Sprite data is in the form of bytes or hexadecimal and you will want to understand
+binary to hex conversions for this. For example, to draw an 8x8 circle, all the
+pixels on should be a 1 in binary and each row needs to be converted to hex:
+```
+0 0 1 1 1 1 0 0 =3C
+0 1 0 0 0 0 1 0 =42
+1 0 0 0 0 0 0 1 =81
+1 0 0 0 0 0 0 1 =81
+1 0 0 0 0 0 0 1 =81
+1 0 0 0 0 0 0 1 =81
+0 1 0 0 0 0 1 0 =42
+0 0 1 1 1 1 0 0 =3C
+```
+So the data would be `3C4281818181423C` in hexadecimal.
+
+### Sprite Logic
+There are 5 forms of sprite logic offered by Grammer, currently. These tell how
+the sprite should be drawn and can all be useful in different situations.
+
+* Overwrite
+  * For an 8x8 sprite, this will erase the 8x8 area on the screen and draw the sprite.
+
+* AND
+  * This leaves the pixel on the screen on if and only if the sprites pixel is on and the pixel on the screen is on.
+
+* OR
+  * This will turn a pixel on on the screen if it is already on or the sprite has the pixel on. This never erases pixels.
+
+* XOR
+  * If the sprites pixel is the same state as the one on the screen, the pixel is turned off, otherwise, it is turned on. For example, if both pixels are on, the result is off.
+
+* Erase
+  * Any pixels that are on in the sprite are erased on screen. The pixels that are off in the sprite do not affect the pixels on the graph buffer.
+
+### Displaying Sprites
+`Pt-On(` is used to display sprites as tiles. This means it displays the sprite very quickly, but you can only draw to 12 columns.
+
+`Pt-Off(` is a slightly slower sprite routine, but it allows you to draw the sprite to pixel coordinates.

+ 75 - 0
docs/fonts.md

@@ -0,0 +1,75 @@
+# Fonts
+Grammer has two built-in fonts, and currently supports three kinds of font.
+
+## Default 4x6
+The default font is a 4x6 fixed-width font. Each character is packed into
+3 bytes, making the entire font set (256 chars) 768 bytes. If you would like to
+create your own font in this format, you can use DrDnar's
+[Monochrome Font Editor](https://github.com/drdnar/MFE/releases).
+
+I recommend loading Grammer's [fixed font file](../../src/gramfont_fix.mfefont)
+as a template.
+
+If you are making a font from scratch, I recommend using these settings in MFE:
+- `Windows>Chart` to display the chart
+- `Windows>Font Properties` to open font properties
+  - Set `Height` to 6
+  - Deselect the `Data Width Multiple of 8` option
+  - Deselect the `Variable Width` option
+  - Set `Data Width` to 4
+  - Set `Width` to 4
+
+
+When you are ready to export the font data, Go to `Windows>Export` and select
+`Xeda's Format #1`. Then save it and MFE generates a `.asm` file with the right
+format for the font data. You can then compiled it with something like spasm
+to an appvar:
+```
+  spasm myfont.asm myfont.8xv
+```
+
+Send `myfont.8xv` to your calc, and now you can use it in Grammer :)
+
+
+## Variable Font
+Grammer also has a built-in variable-width font that is 7 pixels tall. It is
+basically a large font that looks better than the OS large font. This format
+is set up so that the first byte is the height for the entire font, followed by
+all of the char data. Each char is prefixed with a width byte (width in pixels)
+followed by data. Each row of pixels is padded to a multiple of 8 bits. So say a
+char is 5 pixels wide. Then each row is 8 bits (1 byte), with the bottom 3 bits
+being 0.
+
+(Yes, you can have very large fonts.)
+
+As with the fixed-width font, you can use DrDnar's
+[Monochrome Font Editor](https://github.com/drdnar/MFE/releases).
+
+I recommend loading Grammer's
+[variable font file](../../src/gramfont_var.mfefont) as a template.
+
+If you are making a font from scratch, I recommend using these settings in MFE:
+- `Windows>Chart` to display the chart
+- `Windows>Font Properties` to open font properties
+  - Set `Height` to your font height (you choose)
+  - **Select** the `Variable Width` option
+
+
+When you are ready to export the font data, Go to `Windows>Export` and select
+`Xeda's Format #2`. Then save it and MFE generates a `.asm` file with the right
+format for the font data. You can then compiled it with something like spasm
+to an appvar:
+```
+  spasm myfont.asm myfont.8xv
+```
+
+Send `myfont.8xv` to your calc, and now you can use it in Grammer :)
+
+## Omnicalc and Batlib Fonts
+Omnicalc fonts are used by Omnicalc and (Batlib) to replace the OS large font.
+These are 5x7 fonts, so each char takes 7 bytes. Omnicalc fonts have a special
+header, which is why the Grammer docs say they need an offset of 11 bytes.
+Batlib fonts don't have a header, so you don't need to offset. You can use
+DrDnar's font editor to create your font, or download from a multitude of
+available fonts from TICalc.org. If you use DrDnar's MFE, I think it exports
+directly to an appvar or program file.

+ 225 - 0
docs/grammer2.5.inc

@@ -0,0 +1,225 @@
+;===============================================================================
+; Useful TI-OS Equates
+;===============================================================================
+#define bcall(x) rst 28h \ .dw x
+#define rMov9ToOP1    20h
+#define rFindSym    10h
+
+_FindAlphaDn    = 4A47h
+_FindAlphaUp    = 4A44h
+_RclAns         = 4AD7h
+_ChkFindSym     = 42F1h
+_DispHL         = 4507h
+_CreateTempStr  = 4324h
+_SetParserHook  = 5026h
+_CreateVar      = 4E70h
+_CreateAppVar   = 4E6Ah
+_CreatePict     = 4333h
+_EnoughMem      = 42FDh
+_InsertMem      = 42F7h
+_Get_Tok_Strng  = 4594h
+_DelMem         = 4357h
+_JForceCmdNoChar= 4027h
+_JError         = 44D7h
+_DelVarArc      = 4FC6h
+_CreateStrng    = 4327h
+_CreateReal     = 430Fh
+_SetXXXXOP2     = 4792h
+_Arc_Unarc      = 4FD8h
+_ConvKeyToTok   = 4A02h
+_GetKeyRetOff   = 500Bh
+_RunIndicOff    = 4570h
+_DeleteTempPrograms = 5041h
+_MemChk         = 42E5h
+_clrTxtShd      = 454Ch
+_saveCmdShadow  = 4573h
+_PutS           = 450Ah
+_OP5ToOP1       = 413Bh
+_OP1ToOP5       = 4153h
+_VPutMap        = 455Eh
+_Load_LFontV    = 806Fh
+_SFont_Len      = 4786h
+appErr1         = 984Dh
+appErr2         = 985Ah
+cxErrorEP       = 8595h
+curRow          = 844Bh
+curCol          = 844Ch
+kbdScanCode     = 843Fh
+basic_prog      = 9652h
+progStart       = 965Bh
+parsePtr        = 965Dh
+progEnd         = 965Fh
+parserHookPtr   = 9BACh
+tokenHookPtr    = 9BC8h
+OP1             = 8478h
+OP2             = 8483h
+OP3             = 848Eh
+OP4             = 8499h
+OP5             = 84A4h
+OP6             = 84AFh
+flags           = 89F0h
+saveSScreen     = 86ECh
+textShadow      = 8508h
+plotSScreen     = 9340h
+progPtr         = 9830h
+FPS             = 9824h
+OPS             = 9828h
+smallEditRAM    = 90D3h  ;108 bytes
+iMathPtr1       = 84D3h  ;10 bytes
+iMathPtr2       = 84D5h
+iMathPtr3       = 84D7h
+iMathPtr4       = 84D9h
+iMathPtr5       = 84DBh
+asm_data_ptr1   = 84EBh
+asm_data_ptr2   = 84EDh
+cmdShadow       = 966Eh  ;128 bytes
+pTemp           = 982Eh  ;bottom of named vars VAT
+appBackUpScreen = 9872h
+ramCode         = 8100h
+tempSwapArea    = 82A5h
+penCol          = 86D7h
+penRow          = 86D8h
+lFont_record    = 845Ah
+
+;==============================
+;Flags
+;==============================
+CursorFlags     = 12
+CursorActive    =   3
+
+onFlags         = 9        ;on key flags
+onInterrupt     =   4      ;1=on key interrupt request
+
+curFlags        = 12       ;Cursor
+fmtEdit         =   0      ;1=format number for editing
+curAble         =   2      ;1=cursor flash is enabled
+curOn           =   3      ;1=cursor is showing
+curLock         =   4      ;1=cursor is locked off
+cmdVirgin       =   5      ;1=nothing has been typed in cmd bfr
+;----------------------------------------------------------------------
+indicFlags        = 18         ;Indicator flags
+indicRun          =   0        ;1=run indicator ON
+shiftFlags        = 18         ;[2nd] and [ALPHA] flags
+shift2nd          =   3        ;1=[2nd] has been pressed
+shiftAlpha        =   4        ;1=[ALPHA] has been pressed
+shiftLwrAlph      =   5        ;1=lower case, 0=upper case
+shiftALock        =   6        ;1=alpha lock has been pressed
+shiftKeepAlph     =   7        ;1=cannot cancel alpha shift
+
+sGrFlags          = 14h
+textWrite         = 7
+
+fontFlags         = 32h
+fracDrawLFont     = 2
+
+hookflags3        = 35h
+tokenHookActive   = 0		;1 = token hook active
+fontHookActive    = 5		;1 = font hook active
+hookflags4        = 36h ;also sysHookFlag2
+parserHookActive  = 1		;1 = parser hook active
+
+appLwrCaseFlag    = 24h
+lwrCaseActive     = 3
+
+;===============================================================================
+
+
+
+;===============================================================================
+; Grammer Equates
+;===============================================================================
+#define MODULE_VERSION 3
+moduleExec      = saveSScreen
+gbuf            = plotSScreen
+pvars           = smallEditRAM
+ThetaPrimeVar   = pvars+106
+TempWord1   = OP6-1       ;2       2
+TempWord2   = TempWord1+2 ;2       4
+TempWord3   = TempWord2+2 ;2       6
+TempWord4   = TempWord3+2 ;2       8
+TempWord5   = TempWord4+2 ;2      10
+textRow     = TempWord5+2 ;1      11
+textCol     = textRow+1   ;1      12
+
+g_ram       = 8020h
+
+FS_begin  = iMathPtr4
+FS_end    = FS_begin+2
+
+BufPtr      = g_ram        ;2
+GrayBufPtr  = BufPtr+2     ;2
+gbuf_temp   = GrayBufPtr+2 ;2
+FontPointer = gbuf_temp+2  ;2
+font_ptr_page=FontPointer+2;1
+g_internal  = font_ptr_page+1
+Ans         = appErr2      ;2
+
+
+;==============================
+; Grammer Flags
+;==============================
+InternalFlag    = 33
+SlowTextFlag    =   0
+IntActiveFlag   =   1
+FactorialFlag   =   2
+errorChecking   =   3
+grayFlag        =   4   ;this determines the checker pattern for the next gray object drawn
+bit32           =   5   ;This determines if the output was 32-bit or not
+Mod2nd          =   6
+nogrampkg       =   7   ;This determines the checker pattern for grayscale mode
+
+UserFlags       = 34
+InvertTextFlag  =   0
+InvertLCDFlag   =   1
+OnBlockFlag     =   2
+baseInput       =   3
+pxlBoundsRes    =   4
+SignedText      =   5
+;    =   6
+;    =   7
+
+ParticleFlag    = 35
+Xis0            = 0
+Xis95           = 1
+Yis0            = 2
+Yis63           = 3
+OffScrn         = 4
+
+InternalFlag2   = 35
+inputflag       = 0
+
+ModeFlags2      = 35
+floatmode       = 5
+
+
+FS_uint8        = 0
+FS_str          = 3
+FS_array        = 4
+;===============================================================================
+; Grammer Jump Table
+;===============================================================================
+#ifndef NO_JUMP_TABLE
+cmdJmp              = $4023
+ProgramAccessStart  = $4026
+CompatCall          = $4029
+SelectedProg        = $402C
+ExecOP1             = $402F
+ParseFullArg        = $4032
+ParseNextFullArg    = $4035
+ParseNextFullArg_Inc= $4038
+ParseCondition      = $403B
+DrawRectToGraph     = $403E
+GraphToLCD          = $4041
+VPutSC              = $4044
+GetKey              = $4047
+GetGrammerText      = $404A
+GetGrammerText_DE   = $404D
+GetGrammerStr       = $4050
+GetKeyDebounce      = $4053
+SearchString        = $4056
+FS_createvar_max    = $4059
+FS_delvar           = $405C
+FS_resize           = $405F
+FS_findvar          = $4062
+ErrMem              = $4065
+#endif

+ 227 - 0
docs/math.md

@@ -0,0 +1,227 @@
+<h1>Table of Contents</h1>
+
+<!-- MDTOC maxdepth:6 firsth1:2 numbering:0 flatten:0 bullets:1 updateOnSave:1 -->
+
+- [Math](#math)   
+- [Floating Point](#floating-point)   
+- [Number System](#number-system)   
+- [Binary Lesson](#binary-lesson)   
+   - [Converting from Dec to Hex](#converting-from-dec-to-hex)   
+   - [Converting from Hex to Dec](#converting-from-hex-to-dec)   
+   - [Binary.](#binary)   
+   - [Octal.](#octal)   
+   - [Other Bases](#other-bases)  
+
+<!-- /MDTOC -->
+
+# Grammer Math
+
+Grammer uses 16-bit math. If you are not familiar with what this means, please look at the [Number System](#number-system) section.
+
+Much of Grammer is numbers and math. For example, when you do something like `"HELLO WORLD→A`, this isn't storing the string anywhere, it is actually storing the location of the string as a 16-bit number. If you don't know what pointers are, you should read the [Pointers](readme.md#pointers) section.
+
+## Math
+
+Grammer math is very different from the math that you are used to. The main
+points are:
+* Math is done right to left
+* All functions in Grammer are math.
+
+For the first point, let's look at an example of the math string 3+9/58-3\*14+2\*2:
+```
+3+9/58-3*14+2*2
+3+9/58-3*14+4
+3+9/58-3*18
+3+9/58-54
+3+9/4
+3+2
+5
+```
+Parentheses are not part of Grammer math, but to give you you can use a space or use a colon between chunks of math to compute
+each chunk in order. In most situations, you should use a colon. So say you want to
+do ((3+4)*(6+3))/6. You have 3 chunks that you can compute in order:
+```
+3+4:*6+3:/6
+7:*6+3:/6
+7*6+3:/6
+7*9:/6
+63:/6
+63/6
+10
+```
+Pretty cool, right? That is actually even more optimized than using parentheses! Now, if you are like me, you might not like the look of that missing remainder of 3 in that division. 63/6 is 10.5, not 10, but Grammer truncates the results. However, a system variable called θ' will contain the remainder after division and other such extra information after math.
+
+Here are the math operations currently available.
+
+| Example | Token | Grammer | Description                                      |
+|:------- |:----- |:------- |:------------------------------------------------ |
+| a+b     | +     | +       | Adds two numbers. If there is overflow, θ'=1, else it is 0.|
+| a-b     | -     | -       | Subtracts two numbers. If there is overflow, θ'=65535, else it is zero |
+| a*b     | *     | *       | Multiplies two numbers. Overflow is stored in θ' |
+| a/b     | /     | /       | Divides two numbers. The remainder is stored in θ'. |
+| a/ b    | `/ `  | `/ `    | Divides two __signed__ numbers. Ex. `65533/ 65535` returns `3` since this is equivalent to `-3/-1`. |
+| a<sup>2</sup> | <sup>2</sup> | <sup>2</sup> | This squares a number. Overflow is stored in θ'. |
+| -a      | (-)   | (-)     | Negates a number. |
+| min(a,b | min(  | min(    | Returns the minimum of two numbers. |
+| max(a,b | max(  | max(    | Returns the maximum of two numbers. |
+| sin(a   | sin(  | sin(    | This returns the sine of a number as a value between -128 and 127. The period is 256, not 360. For example, sin(32) is like sin(45) in normal math. If you need help, take the actual sin(45) and multiply by 128. Rounded, this is 91. So, sin(32)=91. |
+| cos(a   | cos(  | cos(    | This calculates cosine. See notes on sine. |
+| tan<sup>-1</sup>(a[,b   | tan<sup>-1</sup>(  | tan<sup>-1</sup>(    | This calculates arctangent such that `arctan(sin(x),cos(x))=x` using Grammer's integer trig. |
+| e^(a    | e^(   | e^(     | Computes a power of 2. |
+| gcd(a,b | gcd(  | gcd(    | Returns the greatest common divisor of two numbers. |
+| lcm(a,b | lcm(  | lcm(    | Returns the least common multiple of two numbers. |
+| a▶Frac  | ▶Frac | ▶lFactor | θ' contains the smallest factor of the number. Output is a divided by that number. For example, 96▶Frac will output 48 with θ'=2. You can use this to test primality. |
+| √(a     | √(    | √(a     | Returns the square root of the number, rounded down. θ' contains a remainder. |
+| √('a    | √('   | √('     | Returns the square root rounded to the nearest integer. |
+| abs(a   | abs(  | abs(    | Returns the absolute value of a number. If a>32767, it is treated as negative. |
+| rand    | rand  | rand    | Returns a random integer between 0 and 65535. |
+| randInt(a,b | randInt( | randInt( | Returns a random integer between `a` and `b-1`. |
+| ~~a nCr b~~ | ~~nCr~~ | ~~nCr~~ | ~~Returns `a` choose `b`. In mathematics, this is typically seen as n!/((n-r)!r!). I had to invent an algorithm for this to avoid factorials because otherwise, you could not do anything like 9 nCr 7 (9!>65535).~~|
+| !a      | !     | !       | If the following expression results in 0, this returns 1, else it returns 0. |
+| a and b | and   | and     | Computes bit-wise AND of two values. Remember the [Binary Lesson](binary-lesson.md) ? |
+| a or b  | or    | or      | Computes bit-wise OR of two values. |
+| a xor b | xor   | xor     | Computes bit-wise XOR of two values. |
+| not(a   | not(  | not(    | Inverts the bits of a number. |
+| a=b     | =     | =       | If a and b are equal, this returns 1, else it returns 0. |
+| a≠b     | ≠     | ≠       | If a and b are not equal, this returns 1, else it returns 0. |
+| a>b     | >     | >       | If a is greater than b, this returns 1, else it returns 0. |
+| a≥b     | ≥     | ≥       | If a is greater than or equal to b, this returns 1, else it returns 0. |
+| a<b     | <     | <       | If a is less than b, this returns 1, else it returns 0. |
+| a≤b     | ≤     | ≤       | If a is less than or equal to b, this returns 1, else it returns 0. |
+
+## Floating Point
+As of version 2.50.1.0, Grammer is beginning to have support for floating point numbers. Grammer was originally only intended to have 16-bit integer math support. As a consequence, many useful tokens were already in use, making float support convoluted. I want to reinforce this idea, though: Grammer is a 16-bit integer-centric language.
+
+You will have to interface with floats via pointers. Internally, there is a special floating-point storage that holds a few elements for intermediate processing. If this storage gets full, it wraps around and starts overwriting old items. In particular, this can happen in expressions with many operations. For example, `3.14159+.6.789` will overwrite three values-- two for the numbers 3.14159, 6.789, and one for the sum. At the time of this writing, it can hold 8 floats. In the future this might change, but if you need long-term storage, you will need to copy the 4-byte float to somewhere safe. With that in mind, Grammer now supports a special-purpose move operator `→.` that takes a pointer on the left side, `x` and a pointer *var* on the right side, `Y` and copies the 4 bytes at `x` to the memory at `Y`. Floats must start with a number: `.367` will be interpreted as a comment/label (float support was added on top of the existing Grammer framework), whereas `0.367` is interpreted as a float, and returns a pointer to its converted value.
+
+In general, float commands are signified by an operations followed by a `.`. As of this writing, there are a handful of known bugs, so don't count on this for your math homework yet!
+
+| Example | Token | Grammer | Description                                      |
+|:------- |:----- |:------- |:------------------------------------------------ |
+| e       | e     |         | Returns approximately 2.718282 (Euler's number) |
+| π       | π     |         | Returns approximately 3.141596 (pi). If a hexadecimal digit follows, it will instead return the value for the hexadecimal string. |
+| A→.B    | →.    | →.      | Stores the 4 bytes at ptr A to ptr B             |
+| A+.B    | +.    | +.      | Adds the floats at A and B, returns a pointer.   |
+| A-.B    | -.    | -.      | Subtracts the floats at A and B, returns a pointer. |
+| mean(.A,B | mean(. |      | Computes the mean of A and B                     |
+| A*.B    | *.    | *.      | Multiplies the floats at A and B, returns a pointer. |
+| A/.B    | /.    | /.      | Divides the floats at A and B, returns a pointer. |
+| √(.B    | √(.   | √(.     | Computes the square root of the float at A, returns a pointer. |
+| e^(.A   | e^(.  |         | Returns e^A. |
+| 10^(.A  | 10^(. |         | Returns 10^A. |
+| A^.B    | ^.    | ^.      | Returns A^B |
+| abs(.A  | abs(. |         | Returns the absolute value of the float. |
+| -.A     | (-)   |         | Returns the negative of the float. This is the negative token, not minus. |
+| sin(.A  | sin(. |         | Returns the sine of A (in radians).
+| cos(.A  | cos(. |         | Returns the cosine of A (in radians).
+| tan(.A  | tan(. |         | Returns the tangent of A (in radians).
+| sinh(.A  | sinh(. |       | Returns the hyperbolic sine of A.
+| cosh(.A  | cosh(. |       | Returns the hyperbolic cosine of A.
+| tanh(.A  | tanh(. |       | Returns the hyperbolic tangent of A.
+| sin<sup>-1</sup>(.A  | sin<sup>-1</sup>(. |         | Returns the arcsine of A (in radians).
+| cos<sup>-1</sup>(.A  | cos<sup>-1</sup>(. |         | Returns the arccosine of A (in radians).
+| tan<sup>-1</sup>(.A  | tan<sup>-1</sup>(. |         | Returns the arctangent of A (in radians).
+| sinh<sup>-1</sup>(.A  | sinh<sup>-1</sup>(. |       | Returns the hyperbolic arcsine of A.
+| cosh<sup>-1</sup>(.A  | cosh<sup>-1</sup>(. |       | Returns the hyperbolic arccosine of A.
+| tanh<sup>-1</sup>(.A  | tanh<sup>-1</sup>(. |       | Returns the hyperbolic arctangent of A.
+| log(.A[,B  | log(. |      | `log(.A` returns the base-10 logarithm.  `log(.A,B` returns the base-B logarithm of A.
+| rand.   | rand. |         | Returns a random number on [0,1) |
+| A▶Dec   | ▶Dec  | ▶Float  | A is a pointer. This converts the data at the pointer to a float. Can be used on strings, or `Input` for example. |
+| Text(x,y,`.`A |      |    | Displays a float located at A. |
+| A=.B    | =.    |         | Returns an 1 if float A equals float B, else 0. |
+| A≠.B    | =.    |         | Returns an 1 if float A is not equal to float B, else 0. |
+| A>.B    | =.    |         | Returns an 1 if float A is greater than float B, else 0. |
+| A≥.B    | =.    |         | Returns an 1 if float A is greater than or equal to float B, else 0. |
+| A<.B    | =.    |         | Returns an 1 if float A is less than float B, else 0. |
+| A≤.B    | =.    |         | Returns an 1 if float A is less than or equal to float B, else 0. |
+| int(.A  | int(. |         | Converts  a float to a signed integer. |
+
+
+Examples. The following two codes produce the same result, but the first one uses temporary storage that may get overwritten later, and the second one copies values to less volatile storage:
+```
+3.1415926→X     ;Notice it is just storing a pointer, not copying actual data!
+1.2345678→Y
+Text(0,0,.X+.Y
+```
+
+```
+G-T'→X+4→Y      ;Instead of grayscale graphics, we'll use the back buffer as safe storage. No grayscale quadratic formula program here, apparently.
+3.1415926→.X    ;Now we are copying the float from temp storage to safe storage
+1.2345678→.Y
+Text(0,0,.X+.Y
+```
+
+## Number System
+Grammer's number system works like this: Numbers are integers 0 to 65535. This means no fractions, or decimals, though are a few commands that handle larger numbers.
+
+Let's look at this closer. First, why 65535? That is easy to answer. Grammer
+uses 16-bit math. In binary, the numbers are 0000000000000000b to
+1111111111111111b. Convert that to decimal (our number system) and you get 0 to 65535. If you don't understand binary or hexadecimal, see the [Binary Lesson](#binary-lesson)
+section below. Understanding binary and hex is not necessary, but it will help you
+understand why certain commands act the way they do. Plus, it can help you figure
+out some advanced tricks.
+
+Now, let's look at some scenarios. If you overflow and add 1 to 65535, it
+loops back to 0. Similarly, if you subtract 1 from 0, you loop back to 65535.
+Then you can see that 65530+11=5. You also now know that -1=65535. So what happens
+if you multiply 11\*65535? Believe it or not, you will get -11 which is 65536-
+11=65525.(If you ever want to go into more advanced math in college, hold on to
+this info for when you get into Abstract Algebra. You are working with the ring
+**Z**<sub>2<sup>16</sup></sub>).
+
+
+# Binary Lesson
+
+This document was designed to explain the basics of Decimal (our number system),
+Hexadecimal (base16, the ASM number system), and binary (machine code, 0's and
+1's). Again, this is going to be very basic. Check the internet if you want to
+learn more.
+
+## Converting from Dec to Hex
+1. Divide the number by 16. The remainder is the first number. If it is 0 to 9,
+just keep that. If it is 10 to 15, use letters A to F.
+
+2. If the number is 16 or larger, still, divide by 16.
+3. Repeat step 1 and 2 until finished.
+
+Here is an example of 32173 converted to Hex:
+```
+32173/16= 2010 13/16  Remainder=13 “D”
+2010/16= 125 10/16    Remainder=10 “A”
+125/16= 7 13/16       Remainder=13 “D”
+7/16= 7/16            Remainder=7  “7”
+```
+So the number is 7DADh
+
+## Converting from Hex to Dec
+I will start this with an example of 731h:
+```
+1*16^0 = 1
+3*16^1 = 48
+7*16^2 = 1792
+```
+Add them all up to get 1841. Did you see the pattern with the 16<sup>n</sup>?
+
+## Binary.
+Converting to and from binary is pretty similar. Just replace all the 16's with 2's
+and you will have it.
+
+## Octal.
+Replace all the 16's with 8's.
+
+## Other Bases
+Replace the 16's with whatever number you want.
+
+Here is some cool knowledge for spriting. Each four binary digits represents one
+hexadecimal digit. For example:
+`00110101` corresponds to `35` in hexadecimal. This makes it super easy to convert a sprite which is
+binary to hexadecimal! You only need the first 16 digits, so here you go:
+```
+0000 = 0 0100 = 4 1000 = 8 1100 = C
+0001 = 1 0101 = 5 1001 = 9 1101 = D
+0010 = 2 0110 = 6 1010 = A 1110 = E
+0011 = 3 0111 = 7 1011 = B 1111 = F
+```
+
+Division, unfortunately is not as nice as multiplication, addition, or
+subtraction. 3/-1 will give you 0 because it is 3/65535.

+ 154 - 0
docs/modules.md

@@ -0,0 +1,154 @@
+<h1>Table of Contents</h1>
+
+<!-- MDTOC maxdepth:6 firsth1:1 numbering:0 flatten:0 bullets:1 updateOnSave:1 -->
+
+   - [Modules](#modules)   
+   - [Grammer Routines](#grammer-routines)   
+
+<!-- /MDTOC -->
+
+## Modules
+
+Modules help to extend the Grammer language. Unfortunately, there is a lot of overhead involved, so locating and loading routines is rather slow. As such, I recommend modules where speed isn't critical. Where it is, you can still use assembly programs and hex codes.
+
+Here is the format of a module:
+```
+;All routines must be 768 bytes or less
+;They get copied to moduleExec
+#include "grammer2.5.inc"
+  .db "Gram"         ;Magic number
+  .dw MODULE_VERSION ;Minimum module version. Uses the current version.
+  .dw TableSize      ;Number of elements on the table
+  .dw func0
+  .dw func1
+  ...
+.org 0               ;Set the code counter to 0 here
+
+func0: .db "MYFUNC0",$10  \ .dw size_of_func0_code
+  ;func0
+  ;code
+
+func1: .db "MYFUNC1",$10  \ .dw size_of_func1_code
+  ;func1
+  ;code
+
+```
+
+Here is the template that I use:
+```
+;All routines must be 768 bytes or less
+;They get copied to moduleExec
+#include "grammer2.5.inc"
+  .db "Gram"            ;magic number
+  .dw MODULE_VERSION    ;minimum version
+  .dw (mod_start-2-$)/2 ;num elements
+  .dw func0-mod_start   ;offset to func0
+  .dw func1-mod_start   ;offset to func1
+  .dw func2-mod_start   ;
+  ...
+  .dw funcn-mod_start   ;offset to funcn
+mod_start:
+
+func0: .db "func0",$10 \ .dw func1-$-2
+    ;<<code>>
+
+func1: .db "func1",$10 \ .dw func2-$-2
+    ;<<code>>
+
+func2:
+;...
+
+funcn: .db "funcn",$10 \ .dw mod_end-$-2
+    ;<<code>>
+
+mod_end:
+```
+
+There is already a lot of overhead with module look-up and loading, so to
+minimize lookup time a little, Grammer uses binary search to locate functions.
+As a consequence, the table needs to be sorted by their strings. For example, if
+func0 is called "XXX" and func1 is called "AAA", then the table should have
+`.dw func1` before `.dw func0`.
+
+Another issue to take into account is that the code is copied to `moduleExec`.
+At this time, this limits your code to 768 bytes, and also jumps and calls need
+to be relocated if they occur in your code. *This does* **not** *apply to `jr`
+instructions as these jump a relative distance.*
+
+So for example, let's look at this super complicated piece of code and make it even more complicated:
+```
+func0: .db "XXX",$10 .dw func0_end-func0_start
+func0_start:
+  call label
+  ret
+label:
+  ret
+func0_end:
+```
+That call will almost certainly crash. Instead, you need:
+```
+func0: .db "XXX",$10 .dw funco_end-func0_start
+func0_start:
+  call moduleExec+label-func0_start
+  ret
+label:
+  ret
+func0_end:
+```
+Again, this only applies to `jp` and `call` instructions, and only those for routines within the code. You can still make calls to Grammer routines without all the `moduleExec+` stuff.
+
+One final note before we get to Grammer routines: the function names must be terminated by a `0` byte, a space token (`$29`), or an open parentheses (`$10`).
+
+## Grammer Routines
+
+To use the parser and some of the more useful routines, you can use Grammer's
+jump table. **NOTE:** *This jump table might change in the future, which is why
+the `minimum module version` field is necessary.*
+
+You can use [`grammer2.5.inc`](grammer2.5.inc) for all the equates, available to
+modules.
+
+First, it is important to note that any routines that invoke the parser expect
+BC to hold the "ans" value.
+
+| call                | description | example  |
+|:------------------- |:----------- |:-------- |
+| cmdJmp              | `A` is holds the first byte of the token to evaluate, `(parsePtr)` points to the next byte to parse | Suppose your function mimics `sin(`, given `$C2` is the `sin(` token: `ld a,$C2 \ jp cmdJmp` |
+| ~~ProgramAccessStart~~ | ~~This takes a string in the OS Ans variable as the name of a var. The var is then executed as a Grammer program.~~ | ~~`jp ProgramAccessStart`~~ |
+| CompatCall          | I can't remember. | Sorry. |
+| SelectedProg        | Why tf is this in the jump table? | Just why? |
+| ExecOP1             | OP1 contains the name of the program to execute as Grammer code. | `ld hl,prog_name \ rst rMov9ToOP1 \ jp ExecOP1` |
+| ParseFullArg        | This parses an argument. `BC` is the input, `HL` points to the next byte to parse. **Note:** *Use this to parse the first argument in most cases!* | `call ParseFullArg` |
+| ParseNextFullArg    | This parses an argument. `BC` is the input, `HL` points to the next byte to parse. **Note:** *Use this to parse subsequent arguments!* | `call ParseNextFullArg` |
+| ParseNextFullArg_Inc | `HL` points to the byte before the code to parse. | `ld hl,my_code \ call ParseNextFullArg_Inc \ ...` |
+| ParseCondition      | Use this to parse a condition, as in for `While`, `Repeat`, etc. | `jp ParseCondition` |
+| DrawRectToGraph     | See [drawrect.z80](../src/gfx/drawrect.z80) | Draw an inverted rectangle in the upper-left quarter of the screen: `ld a,2 \ ld bc,$0000 \ ld de,$3020 \ call DrawRectToGraph`        |
+| GraphToLCD          | This copies the gbuf to the LCD. (BufPtr) and (GrayBufPtr) point to the primary and secondary buffers respectively. | `call GraphToLCD` |
+| VPutSC              | `B` is the char to draw, (textrow) and (textcol) are where to draw | Draw an exclamation point at (x,y): `ld hl,$xxyy \ ld b,'!' \ call VPutSC` |
+| GetKey              | This reads the current keypress into the `A` register. | `call GetKey` |
+| GetGrammerText      | This is used to convert a token string to an ASCII string. `HL` points to the start, returns `BC` is the size, `DE` points to the converted string. | `ld hl,tok_str \ call GetGrammerText` |
+| GetGrammerText_DE   | This is used to convert a token string to an ASCII string. **`DE` points to where to output the converted text** `HL` points to the start, returns `BC` is the size, `DE` points to the converted string. | Convert from the string at HL to OP1: `ld hl,tok_str \ ld de,OP1 \ call GetGrammerText_DE` |
+| GetGrammerStr       | Gets the size of a token string. HL` points to the string. Returns `BC` as the size, `HL` points to the end of the input string. | `ld hl,tok_str \ call GetGrammerStr` |
+| GetKeyDebounce      | This reads a debounced keypress into the `A` register. This is best for things like menus where you don't want key presses to be *too* fast. | `call GetKeyDebounce` |
+| SearchString        | Use this to find a substring within a string. See [searchstring.z80](../src/cmd/searchstring.z80) | _ |
+
+If you wanted to make your own addition routine that looked like:
+```
+$ADD(x,y
+```
+
+Your module code would look something like:
+```
+func_add: .db "ADD",$10 \ .dw nextfunc-$-2
+
+    call ParseFullArg     ;parse the first argument
+    push bc               ;Save the result
+    call ParseNextFullArg ;parse subsequent arguments
+    pop hl        ;pop first arg back into HL
+    add hl,bc     ;Second arg in BC. Add the two.
+    ld b,h        ;\ Store the result in BC
+    ld c,l        ;/
+    ret
+
+nextfunc:
+```

+ 769 - 0
docs/readme.md

@@ -0,0 +1,769 @@
+<style>
+a{
+  text-decoration: none;
+  font-weight: bold;
+  border-bottom: 1px dotted gray;
+  color: black;
+}
+</style>
+
+An HTML version of this file is in the `readme` folder :)
+
+# Commands and Tutorial
+```
+Author........Zeda Thomas
[email protected]
+Project.......Grammer
+Version.......2.50.7.1    (I will probably forget to change this :( )
+Last Update...7 November 2019
+Language......English
+Programming...Assembly
+Size..........2-Page app
+```
+
+Hey! You! This app is still in development! If you have issues, please send me an email, post in the forums, or, post an issue on GitHub! Thanks, you're the best :)
+
+
+To follow the progress of Grammer, check out [Omnimaga](https://www.omnimaga.org/grammer/), [Cemetech](http://www.cemetech.net/forum/viewforum.php?f=71) or [GitHub](https://github.com/Zeda/Grammer2), where development is most active.
+
+If you have questions or suggestions, feel free to email me or post in the forums!
+
+<h1>Table of Contents</h1>
+
+<!-- MDTOC maxdepth:6 firsth1:1 numbering:0 flatten:0 bullets:1 updateOnSave:1 -->
+
+- [Commands and Tutorial](#commands-and-tutorial)   
+   - [Intro](#intro)   
+   - [Getting Started](#getting-started)   
+   - [Your First Program](#your-first-program)   
+   - [Pointers](#pointers)   
+   - [Math](#math)   
+   - [Drawing](#drawing)   
+   - [Fonts](#fonts)   
+- [Command List](#command-list)   
+   - [Basic Operations](#basic-operations)   
+   - [Loops/Conditionals/Blocks](#loopsconditionalsblocks)   
+      - [Examples With Blocks](#examples-with-blocks)   
+   - [Control](#control)   
+      - [Control Examples](#control-examples)   
+   - [Input/Computing](#inputcomputing)   
+      - [Input Vars!](#input-vars)   
+      - [Input Examples](#input-examples)   
+   - [solve(](#solve)   
+   - [Physics](#physics)   
+   - [Miscellaneous](#miscellaneous)   
+   - [Data Structures](#data-structures)   
+   - [Memory Access](#memory-access)   
+   - [Data Structures, continued](#data-structures-continued)   
+   - [Modes](#modes)   
+      - [Fix](#fix)   
+      - [Output(](#output)   
+      - [Mode Examples](#mode-examples)   
+- [Charts](#charts)   
+   - [Key Codes](#key-codes)   
+- [Examples](#examples)   
+- [Thanks](#thanks)   
+
+<!-- /MDTOC -->
+
+
+## Intro
+Grammer is a powerful programming language for the TI-83+/84+/SE calculators.
+Unlike TI-BASIC, it is not designed to do math and as such, Grammer math is fairly
+limited in some respects. This also means, however, that it uses a math system with
+its own tricks and optimizations. If you are going to learn how to effectively use
+Grammer, you will first need the Grammer interpreter on your calculator (this
+document assumes you have the latest version of the Grammer App). After that, you
+should become familiar with Grammer's:
+* Number system
+* Math
+* Pointers
+* Drawing
+* Data structures (sprites, arrays)
+
+## Getting Started
+First, send Grammer 2 to your calculator. If you have this document, I assume you have the App.
+Next, run the app on your calc. Grammer is now installed until your next RAM clear.
+The  app's menu controls are as follows:
+
+* [Clear] exits
+* [Up/Down] scroll through the filtered list of programs and appvars
+* [Enter] selects a program or appvar to run as a Grammer program
+* [*] toggles archived/unarchived
+* [Y=] toggles the `Gram` filter. This shows only files with a Grammer header.
+* [Window] toggles the `AppV` filter. Toggled on, this will only show appvars, off will show progams and appvars.
+* [Zoom] toggles the `Asm` filter. Toggled on, this will only show assembly programs.
+* [Trace] exits the app, like [Clear].
+* [Graph] shows more options. At the moment, enable/disable the lowercase and the token hook.
+
+![Grammer Main Menu-- (Default) Grammer programs only](https://i.imgur.com/w8HdE5Q.png)
+
+![Grammer Main Menu-- All Programs and Appvars](https://i.imgur.com/yfXOz7P.png)
+![Grammer Main Menu-- Appvars Only](https://i.imgur.com/azgclwr.png)
+![Grammer Main Menu-- Assembly Programs Only](https://i.imgur.com/wbWStSQ.png)
+![Grammer Main Menu-- More options menu](https://i.imgur.com/WiDA6Ib.png)
+
+## Your First Program
+If you want to make a program, you have to remember two very important things:
+* Start the program with `.0:`
+  * This lets Grammer know it is a Grammer program
+* End the program with Stop.
+  * This lets Grammer know to stop executing code.
+
+Now, before I explain all the technical stuff, could you to create this program and
+run it?
+```
+:.0:Return
+:ClrDraw
+:Text(0,0,"YUM
+:DispGraph
+:Stop
+```
+It should look like this:
+
+!["Yum" example.](https://i.imgur.com/fPqKxCD.png)
+
+
+## Pointers
+To understand pointers, you have to understand how memory works. First, every byte of memory has what is called an address. An address, is a pointer to that byte. For example, the first byte of memory is at address 0, the second byte is at address 1, et cetera. On these calcs, there are 65536 bytes of memory addressed at a time. The last 32768 bytes are RAM. This is where your program and everything in it is stored. This has some powerful implications. If you have a pointer to a section of code and you tell Grammer to start executing there, it can jump there immediately. If you have a pointer to a string, you can use that pointer to draw the string or use it. This means you don't have to create any external variables for your strings or sprites. If you want to create an appvar for save data, having the pointer to that lets you edit the data, save to it, or read from it. Pointers are powerful. As such, you will probably be using them frequently. It is not coincidence that Grammer vars hold 16 bits and pointers are 16-bit.
+
+Vars are two byte values. These can hold a 16-bit number, so these are well suited to holding pointers. These are all the letters `A` to `Z` and `θ` and `A'` to `Z'` and `θ'`. For readability, you can use the lowercase letters instead of `A'`, for example.
+
+How do you store to these? Like all BASIC programmers know, use `→`. For example: `3→A`  
+Likewise, for a string: ```"Hello World→A```  
+Don't be fooled, that does not store the string anywhere. It just stores where the string is located in A.
+So if you change the byte at A, you will change the "H" in your program. If you want to try it, run this program and then check the source again.
+```
+:.0:
+:"HELLO WORLD→A
+:int(A,47
+:Stop
+```
+You will see that after running the program, it now says `"QuartReg ELLO WORLD"` ! That is because we changed the first byte of the string to the value `47`, which corresponds to the token `QuartReg `. Be careful! Not all tokens are one byte-- lowercase letters are a notorious example of two-byte tokens.
+
+Pointers are also useful with labels or finding programs. Anything that requires searching, actually. For example, to goto a label, you would do something like `Goto Lbl "HI` and that would jump to the label named `.HI`. You can also get a pointer to this label. If you need to jump to that label often, this saves lots of time by not having to search for the label every time. Remember, everything is math in Grammer:
+```
+:.0:Return
+:Lbl "HI→A          ;Locates the label .HI and stores its pointer to A.
+:Repeat getKey(15   ;`getKey(15` returns 1 if clear is being pressed
+:prgmA              ;This calls the subroutine pointed to by A
+:End
+:Stop
+:.HI
+:B+1→B
+:Text('0,0,B        ;Displays the number B at (0,0)
+:DispGraph
+:End                ;End the subroutine
+```
+Remember to always `End` your subroutines! Now I want to take time to finally start explaining some code. Labels can be a bit more descriptive than in BASIC. You can use up to 42 bytes for a name, technically, but try to maintain readability. You can also use pretty much whatever tokens you want in a label name. For example, I had a label named `ICircle(` that I had draw inverted filled circles. `Lbl ` takes a string argument where the string is the name of a label. It returns the pointer to the line *after* the label.
+
+
+`Goto ` and `prgm` let you redirect your program. `Goto ` jumps to the code and `prgm` will execute the code and return once it gets to `End`. Both of these take a pointer to figure out where to go.
+
+`Repeat` works like it does in TI-BASIC. It first executes the code between `Repeat`...`End` and then it tests the condition. If the result is 0, it repeats the procedure. If it is anything else, it stops looping and continues after the `End`.
+
+`getKey` gives you two ways to read keys. Key codes are different in Grammer from TI-BASIC. The first way is to use it like you would in TI-BASIC. For example, `getKey→A` stores the current keypress in A. You can also use something like `getKey(15` to quickly test a specific key. This is great if you want to use multiple key presses. I shamelessly stole this wonderful idea from Axe, I think. Or maybe somebody suggested it to me? I can't remember.
+
+## Math
+See the [Math](math.md) documentation.
+
+## Drawing
+See the [Drawing](drawing.md) documentation and the [Drawing Commands](tutorials/drawing.md).
+
+## Fonts
+You can use DrDnar's [Monochrome Font Editor](https://github.com/drdnar/MFE/releases)
+to generate fonts! It supports many kinds of font formats, including Grammer fonts.
+
+If you want to create a font from scratch, you can check the technical
+documentation [here](tutorials/fonts.md).
+
+# Command List
+
+Here are a bunch of commands that do not fit in the drawing or math category. This is a whole
+lot of info (about 9 pages), but I made some examples later on so that you can figure out how to use these better :)
+
+## Basic Operations
+| Example | Token | Grammer | Description / Example |
+|:------- |:----- |:------- |:----------- |
+| a→b     | →     | →       | Stores a value to a var. Ex. `Return→A'` will store the value output from `Return` to `A'`.
+| a→ib    | →i    | →i      | Stores a Grammer variable to an OS Real variable. For example, `3→iA` will store to the OS Real var `A`.
+| a→Str1  | →Str* | →Str*   | Stores a Grammer string to an OS string variable. For example, `"Hello→Str2` will store to Str2, and `"Hello→Str20` will store to the hacked string 20. Keep in mind that the Str0 token corresponds to string 10.
+| a→bc    | →     | →       | Stores a 32-bit value in two variables. `→AB` will store `Ɵ'` in `A` and `Ans` in `B.` So to store a 32-bit result from multiplication: `A*D→AB`.
+| //      | //    | //      | This is used to start a comment. The comment goes to the end of the line. A commented line is skipped. As a note, the user can include a comment after code.
+| "       | "     | "       | This starts a string. The output is a pointer to the string that can be used to reference it later.
+| π       | π     | π       | If you put a `π` symbol before a number, the number is read as hexadecimal. For example, `π3F` would be read as `63`. If what follows is a non-hexadecimal character, this returns a pointer to the float value of pi.
+| !       | !     | !       | This has several uses. The first is to work like the `not()` token in TI-BASIC. So for example, `3=4` would return `0` because it is not true. However, `!3=4` would return `1`. Likewise, `!3=3` would return `0`. The other use is with loops and `If `. For example, `If A=3` will test if `A` is `3` and if it is, it executes the code. However, `!If A=3` will execute the code if `A` is *not* `3`. See [If](#if) , [If-Then](#if-then), [If-Then-Else](#if-then-else), [While](#while), [Repeat](#repeat), and [Pause If](#pause-if).
+| i       | i     | i       | This is the imaginary i. Use this to access OS real vars. For example, to read OS var `A` and store it to Grammer var `A`: `iA→A`. To store a Grammer var to an OS var: `B'→iA`. This does not read decimals or imaginary parts of a number.
+| E       | E     | E       | This indicates the start of a binary string. This is the exponential `E`.
+
+
+## Loops/Conditionals/Blocks
+
+| Name         | Description |
+|:------------ |:------- |
+| If <expr>    | If the expression following is not `0`, the line following it will be executed. The line is skipped if it is `0`. Conditions are computed to the next newline. For example, you can have `→` and `:` in an `If` statement in Grammer.
+| If-Then      | This is similar to `If` except if the statement results in `0`, any code between and including `Then` and `End` will be skipped. This works like the TI-BASIC command.
+| If-Then-Else | This is similar to `If-Then`, except if the condition is non-zero, only the code between `Then` and `Else` is executed, otherwise the code between `Else` and `End` is executed.
+| !If <expr>   | Like `If`, but executes if the condition is false.
+| !If-Then     | Like `If-Then`, but inverts the condition.
+| !If-Then-Else | Like `If-Then-Else`, but inverts the condition.
+| For(         | The arguments for this are `For(Var,Start,End`. `Var` is the name of a var, `Start` is the starting value to load to the var. `End` is the max value to load to the var. Executes the loop, incrementing the variable each time until Var=End
+| For(<<expr>> | The arguments for this are `For(#loops`. `#loops` is how many times the `For` loop will... loop. This is useful if you need it to loop without actually affecting a variable.
+| Pause If     | This will pause so long as the condition is true for example, to pause until a key is pressed, `Pause If !getKey`.
+| !Pause If    | This will pause while the condition is false. So to pause until enter is pressed, do `!Pause If 9=getKey`.
+| While <condition> | Executes what is between `While...End` so long as the condition is non-zero.
+| !While <condition> | Executes what is between `!While...End` so long as the condition is zero.
+| Repeat <condition> | Executes what is between `Repeat...End` and continues to do so as long as the condition is zero.
+| !Repeat <condition> | Executes what is between `Repeat...End` and continues to do so as long as the condition is non-zero.
+| `▶Nom(`x,y,z | This starts a block in which a defined list of variables is preserved. For example, in `▶Nom(A,B,C: <<code>> :End`, no matter what `<<code>>` does to A,B, and C, they will be restored when the `End` is parsed.
+
+### Examples With Blocks
+
+```
+:If A=B      ;Since A=B is false, the following line is skipped
+:9→A
+```
+Or also:
+```
+:If 3=B→A:*14:-14   ;This is the full statement
+:Text(0,0,"Yay!
+```
+
+```
+:If 3=4
+:Then
+:3→A
+:9→B
+:16→C
+:End
+```
+
+```
+:If 3=4
+:Then
+:3→A
+:9→B
+:Else
+:16→C   ;This is the code that gets executed
+:End
+```
+
+```
+:Repeat getKey=15
+:End
+```
+`!Repeat ` checks if the statement is false in order to end. For example,
+to remain in the loop while Enter is being pressed:
+```
+:!Repeat getkey=9
+:End
+```
+
+```
+:For(R,0,48
+:Circle(32,48,R,1
+:DispGraph
+:End
+:Stop
+```
+```
+:0→A→B
+:While getKey≠15
+:A+1→A
+:B-1→B
+:End     ;This tells the While loop to End / restart!
+```
+
+An example with `▶Nom(`
+```
+:ClrDraw
+:▶Nom(A,B
+:0→B
+:For(A,0,9
+:B+A→B
+:Text('0,0,A
+:Text('6,0,B
+:DispGraph
+:Pause 33
+:End
+:End
+```
+
+## Control
+
+| Name         | Description |
+|:------------ |:------- |
+| Return       | This returns a pointer to the next line of code.
+| Goto         | This is unlike the BASIC `Goto` command. This jumps to a pointer as opposed to a label.
+| Lbl          | This returns the pointer of a label. The argument is a pointer to the label name. For example, `Lbl "HI` will search for `.HI` in the program code. Also, you can specify which variable the label is in. For example, if you wanted to jump to a label in another program, you can add a second argument as the name of the var. For example, to find the label `HI` in prgmBYE: `Lbl "HI","BYE` ***Note:*** *If your label moves, you'll need to manually update the pointer! For example, when creating a variable, or resizing one, or archiving/unarchiving. I recommend doing all of that first, then finding labels. If your label moves, then you might accidentally execute garbage data.*
+| Pause xx     | This will pause for approximately xx/100 seconds. So `Pause 66` will pause for about .66 seconds.
+| Pause        | This will wait for [Enter] to be pressed and released.
+| `prgm`       | This is used to execute a sub routine.
+| `prgm(`      | This executes a subroutine, and sets `?` var to to point to the arguments. For example, `prgm(Z,1,2,3` will call the routine that `Z` points to, and sets `?` to point to the `1`.
+| `]`          | This takes a pvar as an argument. It parses the code at the pointer as an argument, then updates the pointer to point to the next argument. This is useful for parsing arguments passed to a subroutine. Take the example above, if the subroutine that `Z` points to has the code `]?`, then the `1` will be parsed. The next `]?` will parse the `2`, and so on.
+| Func         | The arguments are `FuncPointer[,Counter`. This will automatically execute the subroutine pointed to by <<pointer>> based on Counter. Counter is based on an internal counter, not based on actual timings like seconds or milliseconds. The default is 128. See the [examples](#control-examples) below.
+| Asm(         | This can be used to run an assembly program.
+| AsmPrgm      | This allows you to input an asm code in hex. (C9 is needed)
+| ln(          | This will let you jump forward or backward a given number of lines.
+| <sub>L</sub> | The list <sub>L</sub>. Arguments are <sub>`L`</sub>`line#,[start,[size,[EOL` This let's you execute a specific line number. By default, it starts the line count within the main program, but you can pass an optional start value, an optional size value (default is 32768 bytes long), and an optional End-Of-Line argument (default is 63, the newline token).
+| Param        | `?` points to parameters, this stores those parameter values to variables. For example, if `?` points to `1,2,3,4`, then `ParamA,B,C,D` will store `1` to `A`, `2` to `B`, `3` to `C`, and `4` to `D`. This updates `?`. This is useful for subroutines that take parameters! See the example below.
+| Param'        | This pushes values to the parameter stack. For example, `Param'A,0,1,B+2` pushes the value of A, 0, 1, and B+2 to the stack.
+| Param°        | This pops values off the parameter stack into a var. For example, using the previous `push` sequence, `Param°A,B,C,D` would store the original `B`+2 to `A`, `1` to `B`, `0` to `C`, and the original `A` to `D`.
+| Pmt_Bgn       | This token is located at [Apps][Finance][Up]. This is a var that holds the base location for the parameter stack. Changing this value automatically resets the parameter stack pointer.
+| Pmt_End       | This token is located at [Apps][Finance][Up][Up]. This is a var that holds the end location for the parameter stack.
+| `▶Nom(`x,y,z | This starts a block in which a defined list of variables is preserved. For example, in `▶Nom(A,B,C: <<code>> :End`, no matter what `<<code>>` does to A,B, and C, they will be restored when the `End` is parsed.
+
+### Control Examples
+```
+:Return→L
+:<<code>>
+:Goto L     ;This jumps to the line after "Return→L"
+```
+
+An example with setting an interrupt
+```
+:FuncLbl "DISP
+:Repeat getKey(15
+:<<do stuff>>
+:End
+:Stop
+:.DISP
+:DispGraph
+:End
+```
+That will do DispGraph several times per second automatically.
+
+An example with `▶Nom(`
+```
+:ClrDraw
+:▶Nom(A,B
+:0→B
+:For(A,0,9
+:B+A→B
+:Text('0,0,A
+:Text('6,0,B
+:DispGraph
+:Pause 33
+:End
+:End
+```
+
+Jump three lines with `ln(`
+```
+:ln(3
+:"NOT
+:"Executed
+:"YAY :D
+```
+Or to jump backwards:
+```
+:"YAY :D
+:"Erm...
+:"Yeah...:ln(-3
+```
+
+```
+:ClrDraw
+:Lbl "BoldLine(→Z
+:prgm(Z,rand,rand,rand,rand,1
+:DispGraph
+:Stop
+
+:.BoldLine(
+:ParamA,B,C,D,E
+:Line('A,B,C,D,E
+:Line('A+1,B,C+1,D,E
+:Line('A,B+1,C,D+1,E
+:End
+```
+
+## Input/Computing
+| Name         | Description |
+|:------------ |:------- |
+| getKey       | This returns a value from 0 to 56 that is the current key press. You can use [this chart](#keycodes) for values.
+| getKey(      | `getKey(` will allow you to see if a key is being pressed. For example, `getKey(9` will return `1` if enter is pressed
+| Input        | This allows you to input a string. The pointer to the string is returned. (this is not a permanent location, the data will be overwritten the next time Input is used). To get a value input from the user, you can use `expr(` : `expr(Input →A`. This will store the result to A. `Input` can also take an optional string input. The input string will be displayed after what the user is typing. If you execute this code, I think it'll explain it better. It's honestly pretty cool for a calculator. **See below for information on the [Input vars!](#input-vars)**
+| Menu(        | ~~*This may require the included appvar, GramPkg, to be on your calc (in RAM or archived).*~~ Syntax is, `Menu(y,x,w,"Title","Item0","Item1","Item2","Exit`. It basically makes a pop-up style menu, returning the number of the selected item. Returns 0 if exited due to `[CLEAR]` or `[ON]`. ***Note:** you can append an optional last argument that starts with `'` to specify a default option. For example, if the last argument is `'3` then the third option will be selected by default.*
+| Menu('       | Draws a menu that queries Grammer subroutines for the content to render. Syntax is `Menu('"Title",y,x,height,width,GET_ELEMENT_ptr,SELECT_ELEMENT_ptr`. The subroutine for GET_ELEMENT will receive the index in Ans. Return 0 if out-of-bounds, else return a pointer to the string to draw. The subroutine for SELECT_ELEMENT will receive the index in Ans. Modify this as you want, the result will be returned as the result of the menu. Returns 0 if exited due to `[CLEAR]` or `[ON]`. |
+| Ans          | This will return the value of the previous line.
+| expr(        | This will compute a string as a line of code (useful with `Input`). **See below for more info on [`expr(`](#expr-examples)!**
+| inString(    | This is similar to the TI-BASIC command. This will return the location of a sub-string. The inputs are where to start searching and the string to search for: `inString(SearchStart,SearchString[,maxlength]`. The size of the input string is returned in `Ɵ'` and if there was no match found, 0 is returned.
+| length(      | This will return the size of a variable (in RAM or Archive) as well as the pointer to the data in `Ɵ'`. For example, to get the size of the appvar named `Data`: `length("UData→A`. If the var is not found, -1 is returned.
+| length('     | This is used to search for a line. For example, if you want to find a specific line number in a program, this is what you would use. The syntax: `length('StartSearch,Size,LineNumber,[LineByte`, `StartSearch` is where to begin the search `Size` is how many bytes to search in. 0 will search all RAM. `LineNumber` is the line number you are looking for. `LineByte` is an optional argument for what byte is considered a new line. The output is the location of the string and `Ɵ'` has the size of the string. If the line is not found, the last line is returned instead.
+
+Here is an example with the basic menu:
+```
+Menu(1,1,16,"Title","ITEM 1","ITEM 2","ITEM 3→M
+```
+
+And here is an example using callbacks:
+```
+Lbl "GET→A
+Lbl "SEL→B
+Menu('"Title",2,33,59,30,A,B→M
+Text('0,0,M
+Stop
+
+
+.GET
+→X<26
+If !
+End
+"ITEM A→Z
+int(Z+5,X+65
+Z
+End
+
+
+.SEL
++1
+End
+```
+
+
+
+### Input Vars!
+There are two Input variables that you can store to:
+```
+x→Input       This sets the address of the Input buffer.
+x→Input'      This sets the size of the Input buffer. Remember, 1 byte is used to mark the end of the string!
+```
+### expr( Examples
+`expr(` can be used to evaluate a line of Grammer code, usually from a string. For example:
+
+```
+expr("2+3→X
+```
+And this will set `X` to 5.
+
+That's pretty boring, but it is handy if you want to parse user input:
+```
+expr(Input →X
+```
+***NOTE:** This will evaluate up to a newline (`Input` appends a newline to the user's input).
+This means a user could enter any valid Grammer code, even if it messes with your program's variables!*
+
+This note also means you might have some unexpected behavior. For example, let's try this:
+```
+"Rect(X,Y,15,15,2→Z
+expr(Z
+DispGraph
+```
+That inverts a 15-by-15 rectangle at (x,y), as you might have expected.
+
+![*Graph screen, with the center 15-by-15 pixels inverted*](https://i.imgur.com/pxvzqNF.png)
+
+Now let's try to invert that twice:
+```
+"Rect(X,Y,15,15,2→Z
+expr(Z
+DispGraph
+expr(Z
+DispGraph
+```
+
+![*Egads! An error is thrown!*](https://i.imgur.com/K96TsgX.png)
+
+An error is thrown! Why is this? Well, this will teach something about the internals of the
+Grammer parser. The `"` token basically returns a pointer to the next token. So the first line
+causes `Z` to point to the `Rect(` token:
+```
+    "Rect(X,Y,15,15,2→Z
+     ^
+     Z literally points here
+```
+Since `expr(` parses up to a newline, and we give it the pointer `Z`, `expr(` executes:
+`Rect(X,Y,15,15,2→Z` instead of `Rect(X,Y,15,15,2` as you might expect. So this means
+`Z` is modified by the first `expr(`, so the second `expr(` is trying to read some random
+piece of memory as Grammer code. Ouch!
+
+So the simple fix is to put the `→Z` on the next line:
+```
+"Rect(X,Y,15,15,2
+→Z
+expr(Z
+DispGraph
+expr(Z
+DispGraph
+```
+And now it inverts and then reinverts. Ta-da!
+
+### Useful expr( trick
+Here is a useful trick with `expr(`. Suppose we want to invert a sprite on two buffers (grayscale?)
+display it, then re-invert it (this is useful for showing a sprite, without destroying the graphics
+buffer).
+We could do something like:
+```
+Pt-Off(2,S,Y,X
+Pt-Off(2,S,Y,X,1,8,B
+DispGraph
+Pt-Off(2,S,Y,X
+Pt-Off(2,S,Y,X,1,8,B
+```
+
+But by combining the `Return` command with `expr(`, we can do this:
+```
+Return→Z
+Pt-Off(2,S,Y,X:Pt-Off(2,S,Y,X,1,8,B
+DispGraph
+expr(Z
+```
+
+### Input Examples
+
+```
+.0:Return
+ClrDraw
+Text(°"(x,y)=(           ;ClrDraw sets the cursor to (0,0), so I can use °
+expr(Input ",)→X         ;I get the next input here. The string is ,)
+Text(,+1                 ;This increments the X coordinate.
+expr(Input ")→Y          ;This gets the Y value.
+Pxl-On(Y,X               ;Or whatever you want to do with the coordinates.
+DispGraph
+Stop
+```
+
+`inString(` example.
+```
+:Lbl "DATA→A
+:inString(A,"How→B
+:.DATA
+:HELLOHowdyWoRlD!
+```
+
+
+## solve(
+This is a command subset. Commands start as `solve(#,`
+
+| `#` | Name         | Description |
+|:--- |:------------ |:------- |
+| 0   | CopyVar      | `solve(0,"VarName1","VarName2"[,size[,offset`. This will copy the program named by VarName1 from RAM or archive to a new program named by VarName2. If Varname2 already exists, it will be overwritten. So for example, to copy Str6 to Str7: `solve(0,"DStr6","DStr7`. This returns the pointer to the new var and the size of the var is in Ɵ'. The last arguments are optional. Size lets you choose how many bytes are copied (instead of just copying the whole var). You can also add an offset argument to tell where to start reading from.
+| 1   | CopyDataI    | `solve(1,loc i ,loc f ,size`. This copies data from `loc i` to `loc f` . (Forward direction)
+| 2   | CopyDataD    | `solve(2,loc i ,loc f ,size`. This copies data from `loc i` to `loc f` . (Backward direction)
+| 3   | ErrorHandle  | `solve(3,Pointer`. This will allow your program to have a custom error handler. Pointer is 0 by default (meaning Grammer will handle it). Otherwise, set it to another value and Grammer will redirect the program to that location. The error code is returned in Ans. Ans and Ɵ' are put back to normal when the error handler completes. Errors: `0=ON`, `1=Memory`
+| 4   | CallError    | `solve(4,Error#`. This will execute the error code of a Grammer error. For example, to make a Memory error: `solve(4,1`. Using Error 2, you can input a string for a custom error: `solve(4,2,"Uh-Oh!`
+| 5   | PortWrite(   | `solve(5,port#,value`. This writes to a port. Ports give information about peripherals. You can find ports documentation at [WikiTi](http://wikiti.brandonw.net/index.php?title=Category:83Plus:Ports:By_Address)
+| 6   | PortRead(    | `solve(6,port#`. Reads a byte from the port.
+| 7   | CopyVars     | `solve(7,addr`. Copies the pointer vars to some other location. Currently this requires 108 bytes of space in the new buffer. Good for backing up vars.
+| 8   | OverwriteVar | `solve(8,addr`. Overwrites pointer variables with new data.
+
+Here is an error handler example
+```
+:solve(3,Lbl "ERR
+:<<code>>
+:.ERR
+:If =1        ;Means there was a memory error
+:Stop
+:End
+```
+
+## Physics
+
+| Name         | Description |
+|:------------ |:------- |
+| R▶Pr(        | This will clear the particle buffer.
+| R▶Pθ(        | This will recalculate the particle positions and draw them. If you want to change the particle buffer, just add a pointer argument. `Get("EBUF→A:R▶Pθ(A-2`
+| P▶Rx(        | This will add a particle to the buffer. Just use the pixel coordinate position. For example: `P▶Rx(2,2`
+| P▶Ry(        | This will change the particle effect. `0` is normal sand, `1` is boiling, `2` lets you put in a basic custom rule set. If you want it to check Down, then Left/Right, then Up, use the following pattern: `0000 1000 0110 0001`<sub>2</sub>. That makes it first check down, and if it cannot go down, it then checks left or right, and if it cannot go left or right, it tests up. In decimal, that is 2145, so you would do: `P▶Ry(2,2145`. To make things easier, though, you can just use a string. This will achieve the same effect: `P▶Ry(2,"D,LR,U`. **Note** that you do need the actual string, not a pointer.
+|  P▶Rx('      | This will convert a rectangular region of the screen to particles. The inputs are `P▶Rx('Y,X,Height,Width`. This scans the area for pixels that are turned on and adds them to the current particle buffer.
+
+## Miscellaneous
+
+| Name         | Description |
+|:------------ |:------- |
+| ▶DMS         | Found in the angle menu, this is the "module" token. Modules allow you to extend Grammer's functionality. Grammer comes with a default module which must be included to use some functions (like the `Menu` command). Currently, you can have up to five other modules. For example, if you have a module packaged as an appvar called `MyModule`: `"5MyModule→▶DMS`. In order to execute a function `MyFunc(` from one of the modules, use : `▶DMSMyFunc`. If you have the token hook enabled (from Grammer's main menu), it looks a little cleaner: `"5MyModule→$` and `$MyFunc`, respectively.
+| conj(        | **Warning:** I have no knowledge of musical jargon, so excuse my mistakes. This is a sound command with three inputs. The syntax is `conj(Note,Octave,Duration`. Notes are: 0=C, 1=C#, 2=D, 3=D#, 4=E, 5=F, 6=F#, 7=G, 8=G#, 9=A, 10=A#, 11=B. Octave is 0 to 6. Duration is in 64th notes. So for example, a 32nd dot note uses 3/64th time. Duration is thus 3.
+| conj('       | This sound routine has two different functions `conj('Duration,'Period` or `conj('Duration,DataLoc,Size`. This reads data for the period directly to save time (intead of converting numbers on the fly). Size is the size of the data in words, not bytes.
+
+
+## Data Structures
+Grammer doesn't really have any data structures which is both good and bad.
+Bad because it makes you have to think a little more about how to approach a
+problem, but good in that it allows you to create precisely what you need. This is
+where you will need commands to create variables, insert or remove data, and edit
+the data. I will also try to explain how to create some basic data structures like
+arrays and matrices. First, here are the commands you have to work with:
+
+## Memory Access
+
+| Name         | Description |
+|:------------ |:------- |
+| FindVar( *<small>Get(</small>* | This uses a string for the name of an OS var and returns a pointer to its data. If the variable does not exist, this returns 0. If it is archived, the value returned will be less than 32768. Ɵ' contains the flash page the variable is on, if it is archived, otherwise Ɵ' is 0. As an example, `Get("ESPRITES→A'` would return a pointer to the data of `prgmSPRITES` in `A'`.
+| (            | Use this to read a byte of data from RAM
+| {            | Use this to read a two byte value from RAM (little endian)
+| int(         | Use this to write a byte of data to RAM.
+| iPart(       | Use this to write a word of data to RAM, little-endian (a word is 2 bytes). For example, to set the first two bytes to 0 in prgmHI: `Get("EHI→A:iPart(A,0`
+| MakeVar( *<small>Send(</small>*  | Use this to create Appvars or programs of any size and filled with zeros (so long as there is enough memory). For example, to create `prgmHI` with 768 bytes: `Send(768,"EHI`. Programs must be prefixed with `"E"`, protected programs `"F"` and appvars `"U"`. Lowercase letters are allowed! :)
+| [            | Store a sequence of bytes to a given location. For example, `A[1,2,3,4` will store 4 bytes at A. You can also store some elements as two-byte words by using the `°` token. `A[1,2,3°,4`
+| [[           | Stores a sequence of 2-byte words. `A[[1,2,3,4`
+| [(           | Stores hexadecimal input as raw data. `A[(3C7EFFFFFFFF7E3C`
+| IS>(         | This is used to read memory. The argument is one of the pointer vars. It reads the byte pointed to by the pvar and then the pvar is incremented (so consecutive uses will read consecutive bytes).
+| DS<(         | This is used to read memory. The argument is one of the pointer vars. It reads the byte pointed to by the pvar and then the pvar is decremented (see note on `IS>(`)
+| Archive      | Follow this with a var name to archive the var. For example, to archive `prgmPROG`, do this: `Archive "EPROG`.
+| Unarchive    | Use this like `Archive`, except this unarchives the var
+| Delvar       | Use this like `Archive`, except this will delete a var
+| sub(         | Use this to remove data from a variable. the syntax is: `sub(#ofBytes,Offset,"Varname`. For example, to delete the first 4 bytes of program Alpha: `sub(4,0,"EAlpha`.
+| augment(     | This is used to insert data into a var. The syntax is: `augment(#ofbytes,Offset,"VarName`. For example, to insert 4 bytes at the beginning of appvar `Hello`: `augment(4,0,"UHello`.
+
+Display the first 4 bytes of prgmPROG  using `IS>(`
+```
+:Get("EPROG→Z
+:Text('0,0,IS>(Z,16
+:Text('°IS>(Z,16
+:Text('°IS>(Z,16
+:Text('°IS>(Z,16
+```
+
+## Data Structures, continued
+Now let's make an array! First you need to know what you want. Do you want to
+have 2-byte pieces of data or 1-byte? I like using one byte, so here is what we do:
+```
+:.0:Return
+:Send(256,"VDat→Z   ;We create a TempProg with 256 bytes of data called Dat.
+:Z[rand,rand,rand   ;write 3 random bytes.
+:ClrDraw
+:For(3
+:Text('°Is<(Z       ;Display the value at byte Z. Also increments Z.
+:Text('°",
+:DispGraph
+:End
+:Stop
+```
+That didn't really need a 256-byte variable, but I figured I would show how to
+make one. Anyways, what that did was make a 256-byte tempprog (which the OS
+automatically deletes once control is returned to the OS and you are on the
+homescreen). Then, we stored 3 random values to the first three bytes, then we
+displayed those values with commas after each number. If you want to use that 256
+bytes for a matrix, instead, you can make it a 16x16 matrix and access elements
+using a formula. For example, to read (Y,X): `(Z+X+Y*16`. That means that the data is stored in rows. That is why we take the row number and
+multiply by 16 (that is the number of elements per row). This happens to be the
+syntax that tilemaps are stored (stored in rows).
+
+## Modes
+
+| Name         | Description |
+|:------------ |:------- |
+| Fix Text(    | Use this to set the typewriter delay. The larger the number, the slower the typewriter text is displayed.
+| Fix          | See description below.
+| Full         | This is used to set 15MHz mode. Alternatively, if you add a number to the end `Full0` sets 6MHz, `Full1` sets 15MHz, `Full2` toggles the speed. 15MHz is only set if it is possible for the calc. This returns `0` if the previous speed setting was 6MHz, `1` if it was 15MHz.
+
+| Output(      | See description below.
+
+### Fix
+Use this to set certain modes. For all the modes that you want to set, add
+the corresponding values together. For example, to enable inverse text
+and inverse pixels, use `Fix 1+2` or simply `Fix 3`
+
+Here are the modes:
+* 1-Inverse text
+* 2-Inverse pixels. Now, on pixels mean white and off means black.
+In assembly terms, it reads from the buffer, inverts the data
+and sends it to the LCD.
+
+* 4-Disable ON key. This will allow ON to be detected as a key, too
+* 8-Hexadecimal Mode. (Numbers are read as hexadecimal)
+* 16-PixelTestOOB. Returns 1 for out of bounds pixel tests
+* 32 - Display numbers as signed values.
+
+If you want to use bit logic to set or obtain specific bits or info
+about the current modes, you can do things like this:
+
+Stores the current mode value:
+```
+:Fix →A
+```
+
+Set the first three modes without changing the rest:
+```
+:Fix or 7
+```
+
+Toggles mode 4 (enable/disable [ON] key)
+```
+:Fix xor 4
+```
+
+### Output(
+  This is used to change the font. The syntax is:
+* `Output(0` will change to the default 4x6 font.
+* `Output(1` will change to the variable width font.
+* `Output(2` will allow you to use the 4x6 font at pixel coordinates
+* `Output(3,font` will let use Omnicalc or BatLib styled fonts.
+* `Output(4` will use the OS small font.
+* `Output(5` will use the OS large font.
+* `Output(°#` will change the draw logic (except for the OS fonts).
+  * 0=Overwrite
+  * 1=AND
+  * 2=XOR
+  * 3=OR
+  * 4=DataSwap.......Does nothing
+  * 5=Erase
+Adding another argument to the first three will allow you to choose
+your own custom fontset. The argument simply points to the start of the
+fontset.
+
+The output is a pointer to the fontset (custom or standard set), which could be useful if you wanted to read or process the built-in set.
+
+For `Output(3,` remember that Omnicalc's font data starts at an offset of
+11. So if you have a font called `BOLD`, you would do:
+`Output(3,11+Get("EBOLD`
+
+### Mode Examples
+
+Using the output of `Full`, we can test if a calculator allows 15MHz.
+```
+:Full     ;Sets 15MHz if possible
+:If Full  ;Sets 15MHz if possible, but also returns 1 if the previous `Full` was able to set 15MHz
+:Then
+:Text(0,0,"15MHz possible!
+:Else
+:Text(0,0,"6MHz only :(
+:End
+```
+
+# Charts
+## Key Codes
+You can use this as a guide to the key values output by getKey
+example, Clear=15
+
+![Key Codes](https://i.imgur.com/r3ylxgN.png)
+
+Also, there are the diagonal directions:  
+```5=Down+Left  
+6=Down+Right  
+7=Up+Left  
+8=Up+Right  
+16=All directions mashed
+```
+
+# Examples
+Here is code that changes X and Y based on key presses.
+```
+:X+getKey(3
+:min(-getKey(2,95→X
+:Y+getKey(1
+:min(-getKey(4,63→YParticles
+:.0:
+:0→X→Y
+:Repeat getKey(15
+:R▶Pθ(
+:If getKey(9
+:P▶Rx(Y,X
+:X+getKey(3
+:min(-getKey(2,95→X
+:Y+getKey(1
+:min(-getKey(4,63→Y
+:End
+:Stop
+```
+# Thanks
+I have to give special thanks to Yeongjin Nam for their work on writing a
+better tutorial for Grammer and as well Louis Becquey (persalteas) for their work on
+writing a french readme/tutorial. Both of them have also made many valuable
+suggestions that have helped make Grammer what it is right now. Thanks much!
+Thanks to GModder for the suggestions and (many) bug reports that I would not have found otherwise!
+
+I also thank Hans Burch for reconstructing Grammer 2 after I lost my work. It must have been a tremendous amount of effort and tedium, and I greatly appreciate it. They've continued to provide valuable feedback about bugs and it has been extremely helpful.
+
+Finally, I would like to thank the sites that have let me get the word out about
+this project, especially [Omnimaga](https://www.omnimaga.org/index.php) and [Cemetech](https://www.cemetech.net/).

+ 35 - 0
docs/tutorials/DeckShuffle.md

@@ -0,0 +1,35 @@
+To shuffle a deck of cards, you might be inclined to go the classic TI-BASIC route and write some complicated co-sorting algorithm, but you don't need to!
+The [Fisher-Yates Shuffle](https://en.m.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle) algorithm is way easier and faster. An example implementation in TI-BASIC to shuffle `L1` looks like:
+```
+dim(L1→N
+For(K,N,2,-1
+randInt(1,K→A
+L1(K→B
+L1(A→L1(K
+B→L1(A
+End
+```
+
+In Grammer, it is just about as easy. You need to first initialize your deck with something like:
+```
+.Assume Z points to the deck of 52 cards (52 bytes)
+
+For K,0,51
+WriteB(Z+K,K
+End
+```
+
+Then every time you want to shuffle, just call (assuming `Z` still points to the deck):
+
+```
+.SHUFFLE
+51→K
+While K>0
+randInt(0,K→A
+(Z+K→B
+WriteB(Z+K,(Z+A
+WriteB(Z+A,B
+K-1→K
+End
+End
+```

+ 105 - 0
docs/tutorials/MatchGame.md

@@ -0,0 +1,105 @@
+Let's set up the `prgm`!
+```
+.0:Return               ;Make prgm visible to Grammer
+```
+
+To make any game that involves a list or matrix you need to initiate the deck.
+This involves using an area of safe RAM. Say we wanted a 4 by 4 matrix. A matrix is
+just a list of data. To get the elements of this matrix we will use a formula: `(Z+X+Y*R`.
+
+_Note: The `(` is grammers **read byte** token. The Z is a pointer to the area of ram the list will be located. 
+The **R** is the number of rows we are using for the matrix._
+```
+MakeVar(16,"5List→Z     ;Create an appvar and stores the pointer into Z
+
+For K,0,7               ;Starts counting at 0 and increments K until 7
+
+WriteB(Z+K,K            ;Since K is incrementing we can store the value of K
+                        ;as well as use the pointer plus K to store the bytes.
+
+WriteB(K+8+Z,K          ;Note this makes it so there are to of the same byte for matching!
+
+End                     ;Ends the For loop if K=7
+```
+
+Now we want to shuffle the deck that we made. The OS stores the size of the variable
+2 bytes before it's pointer. So we will use `{Z-2` and store it to `K`. Then we will
+use the Fisher-Yates algorithm implemented in Grammer by Zeda. ([DeckShuffle.md](../tutorials/DeckShuffle.md))
+```
+{Z-2→K
+While K>2
+K-1→K
+randInt(0,K→A
+(Z+K→B
+WriteB(Z+K,(Z+A
+WriteB(Z+A,B
+End
+```
+
+Great! Now we have code that creates the deck and then shuffles it! Now we need to set up graphics...
+```
+For F,0,3                
+For G,0,3
+Text(2+8*F,1+2*G,"O     ;Makes a 4x4 display of small font O's
+                        ;The math is to manipulate where at on the screen the O's will appear
+End
+End
+Rect(1,0,33,33,3        ;Draws a black border around the small display
+DispGraph               ;Displays every thing at once! :D
+```
+
+After setting up the Graphics we shall set up the game variables. 
+We need to do this so that the game will start and run the way we code it to.
+```
+0→X→Y
+8→θ
+```
+
+```
+Repeat !θ  or getKey(55
+```
+```
+Rext(2+8*X,1+8*Y,7,7,2
+DispGraph
+Rext(2+8*X,1+8*Y,7,7,2
+```
+```
+(Z+X+Y*4
+If ≠8 *getKey(5
+Then
+If B
+Then
+→A
+0→B
+Z+X+Y*4
+If ≠D *!B
+Then
+→E
+(E→C
+1→B
+2+8*Y→H
+1+2*X→I
+Text('5,12,C
+DispGraph
+If C≠A
+Pause 30
+Text(5,10,"_ _ _            ;3 Spaces to remove the numbers
+Else
+WriteB(D,8:WriteB(E,8
+Text(F,G,"X
+Text(H,I,"X
+θ-1→θ
+End
+End
+End
+```
+```
+X+getKey(3 -getkey(2
+max(0,min3,Ans→X
+Y+getKey(1 -getKey(4
+max(0,min(3,Ans→Y
+End
+```
+```
+Stop
+```

+ 218 - 0
docs/tutorials/controlflow.md

@@ -0,0 +1,218 @@
+# Control Flow
+
+If you already know how to use BASIC control flow you can skip to the next
+section on Grammer's control flow perks. `If` not, then read up on this section
+before moving on. There is a lot of info to retain.
+
+Control Flow is the ability to control the flow of your program. We do this by
+using commands such as `If`, `While`, `Repeat`, `For`, and `Goto`/`Lbl`.
+
+## Code Blocks and Loops
+
+## Using If-Then-Else
+
+If I use `If` in a program `Then`, *if* the statement is true *then* the
+following code will be executed until the corresponding `End` token is reached.
+
+Code:
+```
+If 1
+Then
+<<<code to execute>>>
+End
+```
+*Note: In Grammer, `true` simply means non-zero, while `0` is `false`, as in
+TI-BASIC.*
+
+However, as in TI-BASIC, if we only need to execute one line of code, `Then` and
+`End` can be omitted.
+
+Code:
+```
+If 1
+<<<code to execute>>>
+```
+
+If I use an `If`, `Then`, and `Else` in a single block _then_ if the statement
+is true, the following code will be executed until the `Else` token. If the
+statement is false the code under `Else` will be executed until the
+corresponding `End` token is reached.
+
+Code:
+```
+If 0
+Then
+<<<code to execute if true>>>
+Else
+<<<code to execute if false>>>
+End
+```
+
+A statement is any block of math to be used after the `If`. I used `1` and `0`
+as to represent not just how `If` sees the equation but all control flow
+commands. However, you can use a variable such as `A` or an expression like
+`A>1` which would return `1` if `A` is greater than `1` and `0` if less than
+`A`.
+
+
+### While loops
+While loops repeat _while_ the statement is true. 
+
+### Repeat loops
+
+
+
+### For loops
+
+
+
+### Pause & Pause If
+A pause is pretty much like a loop. The only difference is the way that it loops. 
+In Grammer Pause can be used in 3 ways, so long as you don't count the `!` modifier. 
+The syntax is as follows...
+```
+Pause xx   ;Pauses for approx. xx/100 seconds(useful for delays)
+Pause If   ;Pauses while a statement is true
+Pause      ;Pauses until [ENTER] is pressed(same as BASIC)
+```
+#### Pause xx
+
+`Pause xx` is kind of like `For xx:End` It repeats that many times. Don't get the 2 mixed up though!
+Let's say you were displaying text and you want to display it in intervals.
+`Pause xx` will allow you to do that. 
+
+Code:
+```
+.0:Return
+102→A
+ClrDraw
+Text(°"Super Cool Text!
+DispGraph
+Pause A       ;This pauses for about 102/100 of a second.
+Text(°" Using Pause !
+Pause 50
+Text(°" Oh and pvars!
+Stop
+```
+
+
+#### Pause
+
+`Pause` is kind of like doing `Repeat getKey(9:End`. It loops over and over until you press [ENTER]
+Its best use is probably waiting for the user to press Enter... ;P
+
+Code:
+```
+.0:Return
+ClrDraw
+Text(°"Press Enter
+DispGraph
+Pause
+Stop
+```
+
+
+#### Pause If
+
+`Pause If` is a way to use conditional statements with Pause. Please remember
+that you can't exit a statement that is always true without pressing [ON].
+There are too ways to use this (as far as I'm concerned). The main use for this
+is to pause and either wait for a keypress, or wait for the keypress to be done.
+
+Code:
+```
+.0:Return
+ClrDraw
+Text(°"Press [MODE]
+!Pause If getKey(55              ;Note the use of the ! modifier
+Text(10,0,"Thanks!
+Stop
+```
+
+You might also want to wait for an interrupt to signal for some reason. In this
+example, `Pause If S` looks like it should loop forever, but the interrupt is
+decrementing S and eventually S will be 0, causing the `Pause If` to finish.
+
+Code:
+```
+.0:Return
+FuncLbl "APPLE
+100→S
+Pause If S
+Text(10,0,"Continues executing once S equals 0.
+Stop
+.APPLE
+ClrDraw
+Text('°S
+GetDec(S
+DispGraph
+End
+```
+Note: This works because interrupts are set. Without them this code wouldn't
+really have a way to exit. 
+
+## Labels and Subroutines
+
+### Lbl
+
+
+
+### Return
+
+
+
+### Goto
+
+
+
+### ▶Nom(
+
+
+
+### Line Jumping With ln(
+
+
+
+### prgm
+
+
+
+#### Passing Parameters
+
+
+
+### Asm(
+
+
+
+### AsmPrgm
+
+## Others
+
+### expr(
+### Interrupts
+Interrupts are pretty handy when you want a task to be able to run separately
+from your main code. For example, with grayscale, maybe you want to be able to
+pause but still have grayscale going:
+
+```
+.0:Return
+
+FuncLbl "Draw         ;Setup the interrupt to execute .Draw
+
+SetBuf(°gbuf'→B       ;Set up the gray/secondary buffer
+2→SetBuf(             ;Set 4-level grayscale
+
+Rect(0,0,16,8         ;Draw a 16x8 rect on the main buffer
+Rect(0,0,8,16,1,B     ;Draw an 8x16 rect on the secondary buffer
+
+!Pause If getKey      ;Now wait for a keypress
+Stop
+
+.Draw
+DispGraph
+End
+```
+This still does DispGraph while the program is Paused!
+
+### Execute a line of code

+ 33 - 0
docs/tutorials/data-types.md

@@ -0,0 +1,33 @@
+# Data Types
+
+```
+   name     You use:
+00=Real         log(    Real Format
+01=List         A       Real Format
+02=Matrix       B       Real Format
+03=EQU          C       Symbol Var
+04=String       D       Symbol Var
+05=Program      E       Named Var
+06=ProtProg     [       Named Var
+07=Picture      ]       Symbol Var
+08=GDB          {       Symbol Var
+09=Unknown      }       Not Supported
+10=UnknownEqu   J       Not Supported
+11=New EQU      K       Not Supported
+12=Complex      L       Real Format
+13=Complex List M       Real Format
+14=Undefined    N       Not Supported
+15=Window       O       Not Supported
+16=ZSto         0       Not Supported
+17=Table Range  1       Not Supported
+18=LCD          2       Not Supported
+19=BackUp       3       Not Supported
+20=App          4       Not Supported
+21=Appvar       5       Named Var
+22=TempProg     6       Named Var
+23=Group        7       Named Var   this can mess stuff up unless you *really* know what you are doing.
+```
+
+Symbol Vars are compatible with each other.
+Named Vars are compatible with each other.
+Real Format variables are a special format generally not supported by Grammer.

+ 152 - 0
docs/tutorials/datastorage.md

@@ -0,0 +1,152 @@
+<style>
+a{
+  text-decoration: none;
+  font-weight: bold;
+  border-bottom: 1px dotted gray;
+  color: black;
+}
+</style>
+# Table of Contents<!-- MDTOC maxdepth:6 firsth1:1 numbering:0 flatten:0 bullets:1 updateOnSave:1 -->
+
+- [Overview](#overview)   
+   - [Get(](#get)   
+      - [Notes](#notes)   
+      - [Examples](#examples)   
+   - [length(](#length)   
+      - [Notes](#notes)   
+      - [Examples](#examples)   
+   - [Send(](#send)   
+      - [Notes and Errors](#notes-and-errors)   
+   - [Unarchive](#unarchive)   
+   - [Archive](#archive)   
+   - [Delvar](#delvar)   
+- [Appvars and Programs](#appvars-and-programs)   
+- [Picture Vars](#picture-vars)   
+- [OS Strings](#os-strings)   
+- [OS Real Vars](#os-real-vars)   
+
+<!-- /MDTOC -->
+
+# Overview
+If you want to store data for long-term use, such as player data or high scores,
+you will need to know how to create, find, and store data to variables. Appvars
+provide the most versatile storage means, while OS strings, picture vars, and
+Real vars have some specialized commands.
+
+## Get(
+To get a pointer to a variable's data, use the `Get(` command, located at
+`[prgm][right][up][up]`. If you are using the Grammer token hook, this is
+renamed to `FindVar(`.
+
+The syntax is `Get("varname"`. This returns a pointer to the data in `Ans`, or 0
+if it doesn't exist. If the pointer is less than 32768, then it is archived.
+
+### Notes
+- The flash page is returned in `Ɵ'`, though it really isn't useful in Grammer.
+- `"varname"` needs to contain a type prefix. See [Data Types](datatypes.md) for
+  more info.
+
+### Examples
+Look for appvar MyVar, and:
+- If it doesn't exist, draw "NOT FOUND"
+- If it exists, but is archived, draw "ARCHIVED"
+- If it exists in RAM, draw the first 10 chars
+
+Note that the prefix for appvars can be `5` or `U`. I'll use `5`.
+
+```
+:.0:Return
+:Get("5MyVar→Z
+:If !Z
+:Then
+:Text(0,0,"NOT FOUND
+:Else
+:If Z<32768
+:Then
+:Text(0,0,"ARCHIVED
+:Else
+:Text(0,0,Z,10
+:End
+:End
+:Dispgraph
+:Stop
+```
+
+## length(
+`length(` was intended to get the size of a variable, but it is probably more
+useful than `Get(`. It takes the same arguments, but it returns the size in
+`Ans`, and the pointer in `Ɵ'`. However, size is returned as `-1` (65535) if it
+doesn't exist.
+
+### Notes
+- If the var doesn't exist, the pointer in `Ɵ'` will NOT be 0. You have to check
+  the size.
+
+### Examples
+Look for appvar MyVar, and:
+- If it doesn't exist, draw "NOT FOUND"
+- if it exists, draw the size
+- If it exists, but is archived, draw "ARCHIVED"
+- If it exists in RAM, draw "UNARCHIVED"
+
+Note that the prefix for appvars can be `5` or `U`. I'll use `5`. As well, I use
+the 32-bit store described in the
+[Basic Operations](../readme.md#basic-operations) section. This will put the
+pointer in `Z` and size in `Ɵ`
+
+```
+:.0:Return
+:length("5MyVar→ZƟ
+:If Ɵ=-1
+:Then
+:Text(0,0,"NOT FOUND
+:Else
+:Text('0,0,Ɵ
+:If Z<32768
+:Then
+:Text(6,0,"ARCHIVED
+:Else
+:Text(6,0,"UNARCHIVED
+:End
+:End
+:Dispgraph
+:Stop
+```
+
+## Send(
+To create a variable, use the `Send(` command, located at `[prgm][right][up]`.
+If you are using the Grammer token hook, this is renamed to `MakeVar(`.
+
+The syntax is `Send(#,"varname"`. This returns a pointer to the data
+
+### Notes
+- `"varname"` needs to contain a type prefix. See [Data Types](datatypes.md) for
+  more info.
+- When the data is newly created, it is filled with null bytes.
+- If the var already exists, it will not be overwritten.
+  **This also means it won't be resized if needed!**
+  - If the var already exists as the wrong size, you might cause a crash when
+    you write to it. Always check the variable info with the [Get(](#get) or
+    [length(](#length) commands!
+
+### Examples
+So as an example, suppose we want to create an AppVar of 100 bytes called
+"MyVar". The prefix for appvars can be `5` or `U`, and I'll use `5`:
+
+```
+.0:Return
+:Send(100,"5MyVar
+:Stop
+```
+
+## Unarchive
+## Archive
+## Delvar
+
+# Appvars and Programs
+
+# Picture Vars
+
+# OS Strings
+
+# OS Real Vars

+ 2 - 0
docs/tutorials/datastructures.md

@@ -0,0 +1,2 @@
+- Matrices and Arrays with Grammer
+  - **Note** Understanding this is key to making games or math related programs. Talk about sprites in this documentation as sprites go along with this.

+ 962 - 0
docs/tutorials/drawing.md

@@ -0,0 +1,962 @@
+<style>
+a{
+  text-decoration: none;
+  font-weight: bold;
+  border-bottom: 1px dotted gray;
+  color: black;
+}
+</style>
+# Table of Contents
+
+<!-- MDTOC maxdepth:6 firsth1:1 numbering:0 flatten:0 bullets:1 updateOnSave:1 -->
+
+- [Table of Contents](#table-of-contents)   
+- [Graphics Tutorial](#graphics-tutorial)   
+   - [DispGraph](#dispgraph)   
+   - [Disp](#disp)   
+   - [ClrDraw](#clrdraw)   
+   - [ClrHome](#clrhome)   
+   - [Shade(](#shade)   
+   - [Text(](#text)   
+      - [Draw text strings](#draw-text-strings)   
+      - [Draw numbers](#draw-numbers)   
+      - [Follow text with more text](#follow-text-with-more-text)   
+      - [Typewriter text](#typewriter-text)   
+      - [Display Text Characters (ASCII, ish)](#display-text-characters-ascii-ish)   
+      - [Display text as ASCII, not tokens](#display-text-as-ascii-not-tokens)   
+      - [Miscellaneous Text Operations](#miscellaneous-text-operations)   
+   - [Pxl-On(](#pxl-on)   
+   - [Pxl-Off(](#pxl-off)   
+   - [Pxl-Change(](#pxl-change)   
+      - [Langton's Ant Example](#langtons-ant-example)   
+   - [Pxl-Test(](#pxl-test)   
+   - [Horizontal](#horizontal)   
+   - [Vertical](#vertical)   
+   - [Screen Shifting](#screen-shifting)   
+   - [Fill(](#fill)   
+      - [Byte Patterns](#byte-patterns)   
+      - [Full buffer copies](#full-buffer-copies)   
+      - [Shift-and-copy](#shift-and-copy)   
+      - [Flames Graphics](#flames-graphics)   
+      - [Fill( command summary](#fill-command-summary)   
+   - [StorePic](#storepic)   
+   - [RecallPic](#recallpic)   
+   - [Rectangles](#rectangles)   
+   - [Line](#line)   
+   - [Circle](#circle)   
+   - [Sprites](#sprites)   
+   - [Tiles](#tiles)   
+   - [Tilemap](#tilemap)   
+      - [Tilemap Method 0](#tilemap-method-0)   
+      - [Smooth Scrolling Tilemap](#smooth-scrolling-tilemap)   
+         - [Init](#init)   
+         - [Full Render](#full-render)   
+         - [Scrolling](#scrolling)   
+         - [Get Tile, Set Tile](#get-tile-set-tile)   
+         - [Example Time](#example-time)   
+
+<!-- /MDTOC -->
+
+# Graphics Tutorial
+Grammer offers much faster graphics over BASIC, but a good understanding of the
+lower-level graphics is what will make your graphics *good*.
+
+The most important graphics command is `DispGraph`, located at
+`[prgm][right][4]`. In Grammer, graphics commands don't get rendered to the LCD
+like they do in BASIC. Updating the LCD is a relatively slow operation on the TI-83+/84+ series of calculators (the physical LCD is much slower than the Z80 processor), so the ability to defer updating the LCD offers the biggest boost
+in speed over BASIC graphics. This ability to defer is also what makes graphics
+smoother.
+
+## DispGraph
+By default, `DispGraph` draws the **graphscreen** to the LCD. Here is an example:
+```
+.0:Return
+DispGraph
+Stop
+```
+When you run this from the homescreen, you will see something like:
+
+*![Image Description: DispGraph, showing the graph screen](https://i.imgur.com/zgm1WsY.png)*
+
+You can also display an arbitrary graphics buffer. If you aren't familiar with graphics buffers, see the section on [Graphics Buffers](../drawing.md#graphics-buffers).
+```
+.0:Return
+DispGraph0
+Stop
+```
+*![Image Description: DispGraph, showing garbage](https://i.imgur.com/y9tsl5u.png)*
+
+This shows garbage because `DispGraph` is reading the start of memory
+(address 0) as if it is graphics data.
+
+## Disp
+Most graphics routines allow you to provide an optional argument designating a
+graphics buffer to draw to. You can also set a default buffer with the `Disp `
+function. For example, `Disp G-T'` (or `Disp π9872` on older versions). Now,
+whenever you draw or update the LCD, that is the buffer that will be used. This
+means you can preserve the graph screen while still using graphics in Grammer.
+Note that `G-T` is the token that you can see near the bottom of the mode menu.
+
+As an example, let's set the secondary buffer as the default buffer and draw
+some text. This will preserve the graphscreen, since we aren't drawing there!
+```
+.0:Return
+Disp G-T`
+Text(0,0,"HELLO, WORLD!
+DispGraph
+Stop
+```
+*![Image Description: Animated GIF displaying "HELLO, WORLD!" on an alternate graphics buffer](https://i.imgur.com/xcQMpKc.gif)*
+
+`Disp ` is also important if you want to use grayscale graphics. For the
+following examples, I will assume you know the basic ideas behind grayscale on
+these monochrome calculators. If not,
+[brush up on grayscale](../drawing.md#grayscale).
+Internally, Grammer cleverly sources data from two graphics buffers to determine
+what to display to the LCD when using `DispGraph`. By default, "both" buffers
+point to the graph screen, so it is always reading the same color pixel from
+both sources, essentially displaying either black, or white, and never
+flickering between the two. Also by default, Grammer sources 50% of the color from
+one buffer, and 50% from the other.
+Here is an example that draws grayscale bars until the user presses `[CLEAR]`:
+```
+.0:Return
+Disp °G-T'        ;Set the secondary buffer to appBackUpScreen, 0x9872
+ClrDraw           ;Clear the primary buffer
+ClrDrawG-T'       ;Clear the back buffer
+Line(0,0,64,48    ;Draws a black rectangle on the left half of the main buffer
+Line(0,0,64,24,1,G-T'    ;Draws a black rectangle on the left quarter of the back buffer
+Line(48,0,64,24,1,G-T'   ;Draws a black rectangle on the third quarter of the back buffer
+Repeat getKey(15  ;Repeat the loop until key 15 ([clear]) is pressed
+DispGraph         ;Display the graph buffers
+End
+Stop
+```
+*![Image Description: The left quarter of the screen is black, the right quarter is white, and the middle half is gray](https://i.imgur.com/m3Ovx4w.png)*
+
+You can change how much color is sourced from each buffer by selecting a
+different gray mask. Grammer has 3 different grayscale modes (0,1, and 2), but
+realistically, modes 1 and 2 are most useful. Mode 1 is the default and
+sources 50% from each buffer. Mode 2 sources 67% from the primary buffer
+and 33% from the back buffer, allowing 4 different shades.
+Adding `2→Disp` to the start of the above code:
+```
+.0:Return
+2→Disp            ;Set to 67-33 grayscale mode
+Disp °G-T'        ;Set the secondary buffer to appBackUpScreen, 0x9872
+ClrDraw           ;Clear the primary buffer
+ClrDrawG-T'       ;Clear the back buffer
+Line(0,0,64,48    ;Draws a black rectangle on the left half of the main buffer
+Line(0,0,64,24,1,G-T'    ;Draws a black rectangle on the left quarter of the back buffer
+Line(48,0,64,24,1,G-T'   ;Draws a black rectangle on the third quarter of the back buffer
+Repeat getKey(15  ;Repeat the loop until key 15 ([clear]) is pressed
+DispGraph         ;Display the graph buffers
+End
+Stop
+```
+*![Image Description: Four vertical bars, each a quarter of the screen wide: Black, light gray, dark gray, white.](https://i.imgur.com/khIQh7P.png)*
+
+
+There is a mode that ORs the two buffers together before displaying.
+This is useful for an independent background (you could probably do paralax
+scrolling with this, or overworld sprites on top of a tilemap). This mode uses
+`16→Disp`.
+
+
+There is another mode useful for tilemaps that masks three buffers. This is
+done using the mode: `17→Disp`. This ANDs the secondary buf with the
+tilemap_buf (used during smooth-scrolling tilemapping). It then XORs that with
+the primary buf. This is fantastic for adding overworld graphics without
+destroying the tilemap data (thus reducing rendering time, making things faster
+and smoother).
+
+## ClrDraw
+`ClrDraw` clears the primary graphics buffer, setting it to white, and resets
+the text coordinates to the upper-left, (0,0). Alternatively, you can specify a
+graphics buffer to erase, for example: `ClrDrawG-T'` would clear the buffer that
+`G-T'` points to (typically used as a back buffer for grayscale).
+
+## ClrHome
+This clears the home screen buffer and resets the cursor coordinates. This isn't
+really useful in Grammer as the homescreen is essentially unused, but it's good
+for aesthetics and advanced users.
+
+## Shade(
+This sets the contrast to a value from 0 to 39. 24 is normal. An example is
+`Shade(30`.
+
+*Note: I am aware that the LCD actually offers 64 different shades, however, I
+deferred to the OS conventions. Why I did this is beyond me, but it's too late
+to change it.*
+
+## Text(
+There are many different methods for drawing text in Grammer.
+By default, it uses a 4x6 fixed-width font, and can draw to 24 columns (much
+like the TI-BASIC `Output(` command drawing to only 16 columns on the
+homescreen). Unlike TI-BASIC, `Output(` is instead used to change font settings.
+This lets you choose between grid-aligned and pixel-aligned drawing, or the
+small, fixed-width font, or the large variable-width font, or even custom fonts
+from Batlib and Omnicalc. You can find more on this in the [Output(](#output)
+section.
+
+### Draw text strings
+The most basic way to use `Text(` looks a lot like BASIC:
+```
+.0:Return
+ClrDraw
+Text(3,1,"HELLO, WORLD
+DispGraph
+Stop
+```
+This draws the text, `"HELLO, WORLD"` at three pixels down and 1 column
+(4 pixels) to the right.
+
+*![Image Description: "Hello, world" is drawn to the graph screen.](https://i.imgur.com/vIIqxSy.png)*
+
+You can also specify how many chars to print, with an  optional fourth argument.
+*Note: this will draw end-of-string characters instead of stopping early!*
+For example:
+```
+.0:Return
+ClrDraw
+Text(4,1,"TOMATO",3
+DispGraph
+Stop
+```
+*![Image Description: "TOM" is drawn to the graph screen.](https://i.imgur.com/Abgbg9h.png)*
+
+Or a little more exciting:
+```
+.0:Return
+ClrDraw
+Text(4,1,"HELLO",17
+DispGraph
+Stop
+```
+*![Image Description: 'Hello, "17 DispGra' is drawn to the graph screen.](https://i.imgur.com/CpcXi3e.png)*
+
+
+### Draw numbers
+To draw a number, use the `'` modifier:
+```
+.0:Return
+ClrDraw
+Text('0,0,1337
+DispGraph
+Stop
+```
+This draws the number 1337 in the upper-left corner of the screen.
+
+*![Image Description: "1337" is drawn to the graph screen.](https://i.imgur.com/3ihVTvB.png)*
+
+When drawing numbers, you can add an optional argument to change what base to
+draw the number in. For example, binary is base 2, so:
+```
+.0:Return
+ClrDraw
+Text('0,0,1337,2
+DispGraph
+Stop
+```
+*![Image Description: "1337" is drawn to the graph screen in binary.](https://i.imgur.com/px7677d.png)*
+
+Grammer uses "16-bit unsigned integers",  but sometimes you'll want to draw
+"signed" numbers. If you don't know what these mean, check out the section on
+[Number Systems](../math.md#number-systems).
+
+To draw numbers as signed values, set the mode flag with `Fix or 32` (see
+[Fix Modes](../readme.md#Modes) for more). Here is an example where we display
+the value of `3-4`, which is `-1`. On the left, we omit the `Fix or 32`,
+so it displays as 65536-1=65535. On the right, we display it as signed, so it
+shows as `-1`
+
+```
+.0:Return
+Fix or 32
+ClrDraw
+Text('0,0,3-4
+DispGraph
+Stop
+```
+*![Image Description: "65535" is drawn to the graph screen.](https://i.imgur.com/xfj4S3t.png)*
+*![Image Description: "-1" is drawn to the graph screen.](https://i.imgur.com/XUNyFii.png)*
+
+Grammer also allows you to draw a 32-bit number stored in two pointer vars.
+An example where B is the upper 16-bits and C' is the lower 16-bits:
+`:Text('0,0,BC'`
+Or a more practical example, we can display a number including the overflow of
+multiplication. We'll make use of the 32-bit store described in the
+[Basic Operations](../readme.md#basic-operations) section:
+```
+.0:Return
+ClrDraw
+39103*136→AB
+Text('0,0,AB
+DispGraph
+Stop
+```
+*![Image Description: "5318008" is drawn to the graph screen.](https://i.imgur.com/8F4CDB5.png)*
+
+
+### Follow text with more text
+If you want to draw text where the last `Text(` command left off, use a degree
+token to replace coordinates: `Text(°`. For example, we'll
+display the numbers 3 and 4 with a comma separating them:
+```
+.0:Return
+ClrDraw
+Text('0,0,3
+Text(°",
+Text('°4
+DispGraph
+Stop
+```
+*![Image Description: "3,4" is drawn to the graph screen.](https://i.imgur.com/0mXpoJT.png)*
+
+Note that `°` came *after* `'` when we wanted to display the `4`. This is because
+the modifier `'` comes before the coordinates when displaying numbers, and `°`
+replaces the coordinates.
+
+### Typewriter text
+"Typewriter text" is text displayed with a small pause between characters drawn.
+To use this effect, you can use `/Text(` or `Text(`<sup>`r`</sup> (that is the
+superscript `r` found at [2nd][APPS]). You can change the delay with `Fix Text(`
+(see [Fix Modes](../readme.md#Modes) for more). *Note: Typewriter text
+automatically updates the LCD.*
+```
+.0:Return
+ClrDraw
+/Text(0,0,"HELLO, WORLD!
+Stop
+```
+*![Image Description: "HELLO, WORLD!" is drawn to the graph screen in typewriter text mode.](https://i.imgur.com/aRxTu8Y.gif)*
+
+Typewriter text works with all of the text modes, not just strings!
+
+### Display Text Characters (ASCII, ish)
+There are 256 characters in the font, some are more difficult to access via the
+OS tokens. In Grammer, you can directly draw chars by number if you put a `'`
+before the last argument. For example, 37 corresponds to the `%` char:
+
+```
+.0:Return
+ClrDraw
+Text(4,1,'37
+DispGraph
+Stop
+```
+*![Image Description: "%" is drawn to the graph screen.](https://i.imgur.com/EZ8FunF.png)*
+
+Note that if we want to draw a char to the last text coordinates, we put the `'`
+*after* the `°`:
+```
+.0:Return
+ClrDraw
+Text('4,1,100
+Text(°'37
+DispGraph
+Stop
+```
+*![Image Description: "100%" is drawn to the graph screen.](https://i.imgur.com/ZyXrE6a.png)*
+
+### Display text as ASCII, not tokens
+Drawing ASCII is **not** intended for drawing text that you type in the program
+editor! If you don't know what a "null terminated string" is, then you probably
+don't want to use this! After this sentence, I will get technical and you should
+probably know Assembly or C to understand it.
+
+In the event that you have an ASCII string that you would like to display, keep
+in mind that it must be null-terminated (ends in a 0x00). Display with the
+syntax, `Text(Y,X,°<<pointer>>`.
+
+
+### Miscellaneous Text Operations
+If you want to draw to coordinates relative to the last drawn coordinates, you
+can do something like this: `Text(+3,+0,"Hello`. But instead of +0, just leave
+it empty like this: `Text(+3,,"Hello`
+
+Using the `Text(` command with no arguments returns the Y position
+in `Ans` and the X position in `Ɵ'`.
+
+You can set the coordinates without drawing text, too: `Text(0,0`.
+
+## Pxl-On(
+The arguments for this are: `Pxl-On(y,x[,buf`.
+This draws a black pixel at coordinates (`y`,`x`), on buffer `buf`. If you omit
+the `buf` argument, this defaults to the current default buffer. As well, the
+previous pixel value is returned, with 0 indicating white, and 1 indicating
+black.
+
+To set the upper-left pixel black, we can do:
+```
+Pxl-On(0,0
+```
+
+To set the bottom-right pixel black:
+```
+Pxl-On(63,95
+```
+
+## Pxl-Off(
+The arguments for this are: `Pxl-Off(y,x[,buf`.
+This draws a white pixel at coordinates (`y`,`x`), on buffer `buf`. If you omit
+the `buf` argument, this defaults to the current default buffer. As well, the
+previous pixel value is returned, with 0 indicating white, and 1 indicating
+black.
+
+To set the upper-left pixel white, we can do:
+```
+Pxl-Off(0,0
+```
+
+To set the bottom-right pixel white:
+```
+Pxl-Off(63,95
+```
+
+
+## Pxl-Change(
+The arguments for this are: `Pxl-Change(y,x[,buf`.
+This toggles a pixel at coordinates (`y`,`x`), on buffer `buf`. If you omit
+the `buf` argument, this defaults to the current default buffer. As well, the
+previous pixel value is returned, with 0 indicating white, and 1 indicating
+black.
+
+To toggle the upper-left pixel:
+```
+Pxl-Change(0,0
+```
+
+To toggle the bottom-right pixel:
+```
+Pxl-Change(63,95
+```
+
+### Langton's Ant Example
+An interesting application of Grammer's `Pxl-Change(` command is with
+[Langton's Ant](https://en.wikipedia.org/wiki/Langton%27s_ant). Because a pixel
+test is built in, we can combine the test+toggle step. Here is an example that
+displays every 250 iterations, but only exits when you press `[Clear]`.
+
+```
+:.0:Return
+:Full
+:ClrDraw
+:0→D→C
+:32→Y:48→X
+:Repeat getKey(15
+:Pxl-Change(Y,X
+:+Ans+D-1
+: and 3→D
+:Y+D=0:-D=2→Y
+:X+D=3:-D=1→X
+:C+1→C
+:If !C and 255
+:DispGraph
+:End
+;Stop
+```
+***Note:*** *the `and 3` and `and 255` tricks only works for powers of 2! `3` is
+2^2-1 and `255` is 2^8-1.*
+
+*![Image Description: Langton's Ant is shown incrementally.](https://i.imgur.com/a4q4Hoc.gif)*
+
+## Pxl-Test(
+The arguments for this are: `Pxl-Test(y,x[,buf`.
+This gets the pixel value at coordinates (`y`,`x`), on buffer `buf`. If you omit
+the `buf` argument, this defaults to the current default buffer. Returns 0 if
+the pixel is off (white), and 1 if the pixel is on (black).
+
+## Horizontal
+This draws a horizontal line on the graph. The syntax is
+`Horizontal y[,method,[,Buffer`
+* `y` is a value from 0 to 63
+* `method` is how to draw the line:
+  * 0 = draws a white line
+  * 1 = draws a black line (*Default*)
+  * 2 = draws an inverted line
+* `Buffer` is the buffer to draw to.
+
+For example, this will make a screen-wiping animation from the up and down
+directions:
+```
+:.0:Return
+:For(K,0,31
+:Horizontal K
+:Horizontal 63-K
+:DispGraph
+:End
+:Stop
+```
+
+*![Image Description: Screen wipe using horizontal black lines.](https://i.imgur.com/g1FIDbu.gif)*
+
+
+## Vertical
+This draws a vertical line on the graph. The syntax is:
+`Vertical x[,method[,Buffer`
+* `x` is a value from 0 to 63
+* `method` is how to draw the line:
+  * 0 = draws a white line
+  * 1 = draws a black line (*Default*)
+  * 2 = draws an inverted line
+* `Buffer` is the buffer to draw to.
+
+For example, this will make a screen-wiping animation from the left and right
+directions:
+```
+:.0:Return
+:For(K,0,47
+:Vertical K
+:Vertical 95-K
+:DispGraph
+:End
+:Stop
+```
+
+*![Image Description: Screen wipe using vertical black lines.](https://i.imgur.com/opfuGa1.gif)*
+
+## Screen Shifting
+`Tangent(` is used to shift the screen a number of pixels. The syntax is:
+Tangent(#ofShifts,Direction[,Buffer
+`#ofShifts` is the number of pixels to shift the graph screen
+`Direction` is represented as a number:
+* 1 = Down
+* 2 = Right
+* 4 = Left
+* 8 = Up
+You can combine directions by adding the values. For example,
+Right and Up would be 10 because 2+8=10, so to shift the buffer contents right
+and up 4 pixels:
+
+```
+Tangent(4,10
+```
+
+## Fill(
+`Fill(` is a whole bunch of commands for buffer operations.
+For example, suppose you want to fill the buffer with black pixels. Then you can
+use `Fill(0)`
+
+```
+:.0:Return
+:Fill(0
+:DispGraph
+:Stop
+```
+*![Image Description: The graph screen is all black, in the background of the homescreen.](https://i.imgur.com/lgqyf1o.png)*
+
+Or to invert the buffer:
+```
+:.0:Return
+:Fill(1
+:DispGraph
+:Stop
+```
+*![Image Description: The graph screen is all black, in the background of the homescreen.](https://i.imgur.com/LxAaTR4.png)*
+
+You can also fill the screen buffer with a checkered pattern. There are two
+versions of this. I don't know how this is useful, but I won't judge:
+```
+:.0:Return
+:Fill(2
+:DispGraph
+:Stop
+```
+```
+:.0:Return
+:Fill(3
+:DispGraph
+:Stop
+```
+*![Image Description: The graph screen is checkered.](https://i.imgur.com/Wp9I4RA.png)*
+*![Image Description: The graph screen is checkered.](https://i.imgur.com/rvGAHYa.png)*
+
+### Byte Patterns
+You can fill the buffer with a byte pattern, too. For example, suppose you want
+to set every other pixel black. You will need to use OR logic, and a byte
+pattern of `85` or `170`. This is because in binary, `85` is `01010101` and
+`170` is `10101010`. So we'll use Fill( method number 4:
+`Fill(4,byte  - LoadBytePatternOR`:
+```
+:.0:Return
+:Fill(4,85
+:DispGraph
+:Stop
+```
+*![Image Description: The graph screen is checkered.](https://i.imgur.com/V2YY6bP.png)*
+
+But you can also use method 5 to invert instead. To alternate inverting 2 pixels
+and then leaving 2 pixels ignored, we use a byte whose binary looks something
+like 11001100. In decimal, this is 204:
+```
+:.0:Return
+:Fill(5,204
+:DispGraph
+:Stop
+```
+In this image I got rid of the axes and drew a sine curve beforehand:
+
+*![Image Description: The graph looks cool.](https://i.imgur.com/pZzJxQX.png)*
+
+### Full buffer copies
+Buffer copies are useful operations, especially for game graphics. These copy
+the data from one buffer to another. The most useful ones are probably the
+masking routines, allowing you to perform such operations as ORing or XORing one
+buffer on top of another.
+This is a little more complicated to show, but in this example, I've copied a
+sine graph into Pic1, and now I'll invert it onto the graphscreen:
+
+```
+:.0:Return
+:Fill(11,Pic1
+:DispGraph
+:Stop
+```
+*![Image Description: Sine XORed on to the graph screen.](https://i.imgur.com/0c3FR7o.png)*
+
+### Shift-and-copy
+These operations are pretty esoteric, honestly, but maybe you can find a use for
+them. These copy the current buffer up or down one pixel, masked back on top of
+the buffer. It can make some neat cellular automata effects, for example:
+```
+:.0:Return
+:For(X,0,95
+:Pxl-On(0,X
+:Fill(16,1
+:DispGraph
+:End
+:Stop
+```
+This marches a pixel on the top row from left to right, while XORing the buffer
+1 pixel down onto itself.
+
+*![Image Description: Shifting in a Sierpinski's Gasket.](https://i.imgur.com/TLgaTui.gif)*
+
+### Flames Graphics
+Flames graphics are pretty cool, and might be useful in games. The flame
+functions have two modes: white fire and black fire. In white fire mode, any
+white pixels on the screen are shifted up and have some probability of turning
+black (dissipating, burning out). In black fire mode, it is the opposite.
+
+Grammer has two commands to use these, one for the whole screen, and one for
+part of the screen. Here is an example where we take the contents of the graph
+screen as constant "fuel." To do this, we need to switch to another default
+buffer, then in a loop, we copy the graph buffer to the new buffer with OR logic
+and then perform one cycle of fire:
+```
+:.0:Return
+:Disp G-T'
+:ClrDraw
+:Repeat getKey(15
+:Fill(9,G-T
+:Fill(22,1
+:DispGraph
+:End
+:Stop
+```
+Note that `G-T` is the token found in the mode menu, or at `[2nd]` `[0]` `[^]` `[up]`.
+
+*![Image Description: The graphscreen, but burning.](https://i.imgur.com/DTckrFW.gif)*
+
+
+### Fill( command summary
+  Stick around, this is a pretty full command list.
+* `Fill(0` - Black
+  * This fills the screen buffer with black pixels
+* `Fill(1` - Invert
+  * This inverts the screen buffer
+* `Fill(2` - Checker1
+  * This fills the screen buffer with a checkered pattern
+* `Fill(3` - Checker2
+  * This fills the screen buffer with another checkered pattern
+* `Fill(4,byte` - LoadBytePatternOR
+  * copies `byte` to every byte of the buffer data with OR logic
+* `Fill(5,byte` - LoadBytePatternXOR
+  * copies a `byte` to every byte of the buffer data with XOR logic
+* `Fill(6,byte` - LoadBytePatternAND
+  * copies a `byte` to every byte of the buffer data with AND logic
+* `Fill(7,byte` - LoadBytePatternErase
+  * copies a `byte` to every byte of the buffer data with Erase logic
+* `Fill(8,buf` - BufCopy
+  * `buf` points to another buffer. The current buffer gets copied there
+* `Fill(9,buf` - BufOR
+  * `buf` points to another buffer. This gets copied to the current buffer with OR logic.
+* `Fill(10,buf` - BufAND
+  * `buf` points to another buffer. This gets copied to the current buffer with AND logic.
+* `Fill(11,buf` - BufXOR
+  * `buf` points to another buffer. This gets copied to the current buffer with XOR logic.
+* `Fill(12,buf` - BufErase
+  * `buf` points to another buffer. This gets copied to the current buffer by erasing.
+* `Fill(13,buf` - BufSwap
+  * `buf` points to a buffer. This swaps the current buffer with the other.
+* `Fill(14,n` - CopyDownOR
+  * The current buffer is copied `n` pixels down to itself with OR logic
+* `Fill(15,n` - CopyDownAND
+  * The current buffer is copied `n` pixels down to itself with AND logic
+* `Fill(16,n` - CopyDownXOR
+  * The current buffer is copied `n` pixels down to itself with XOR logic
+* `Fill(17,n` - CopyDownErase
+  * The current buffer is copied `n` pixels down to itself with Erase logic
+* `Fill(18,n` - CopyUpOR
+  * The current buffer is copied `n` pixels up to itself with OR logic
+* `Fill(19,n` - CopyUpAND
+  * The current buffer is copied `n` pixels up to itself with AND logic
+* `Fill(20,n` - CopyUpXOR
+  * The current buffer is copied `n` pixels up to itself with XOR logic
+* `Fill(21,n` - CopyUpErase
+  * The current buffer is copied `n` pixels up to itself with Erase logic
+* `Fill(22,type` - FireCycle
+  * This burns the contents of the screen for one cycle. If type is 0,
+    white fire is used, if it is 1, black fire is used.
+* `Fill(23,Type,Y,X,Width,Height` - Fire Cycle 2
+  * Type is the same as FireCycle and the other inputs are the same as Pt-On(
+    where X and Width go by every 8 pixels.
+
+## StorePic
+Syntax is: `StorePic pic#[,buf`, where `buf` is an optional argument pointing
+to the buffer to save. By default, `buf` is the current buffer.
+
+This stores the contents of the buffer to an OS Pic var. This automatically
+deletes a preexisting picture. You can use this to store to pictures 0 to 255,
+where 0 = `Pic1`, 1 = `Pic2`, 9 = `Pic0`.
+
+## RecallPic
+Syntax is: `RecallPic pic#[,logic[,buf`, where `buf` is an optional argument
+pointing to where the contents are copied to. By default, `buf` is the current
+buffer.
+
+`pic#` is the picture var to read from, from 0 to 255 where 0 = `Pic1`,
+1 = `Pic2`, 9 = `Pic0`. This works even if the pic var is archived :)
+
+`logic` is:
+* 0 = Overwrite (default)
+* 1 = AND
+* 2 = XOR
+* 3 = OR
+* 5 = Erase
+
+## Rectangles
+*Unfortunately, you use `Line(` to draw rectangles. The excuse for this is that
+when I very first made Grammer 1, I didn't think I'd ever have a line drawing
+routine, but I had rectangles galore. Without forethought, I decided using the
+`Line(` token was quite reasonable. I was wrong.*
+
+This is used to draw rectangles. The syntax for this command is:
+`Line(x,y,Height,Width,Method`
+
+* x is a value from 0 to 95 and is the x pixel coordinate to begin drawing at
+* y is a value from 0 to 63 and is the y pixel coordinate to begin drawing at
+* Height is a value from 1 to 64 is the number of pixels tall the box will be
+* Width is a value from 1 to 96 is the number of pixels tall the box will be
+* Method is what kind of fill you want:
+  * 0-White. This turns off all of the pixels of the rectangle
+  * 1-Black. This turns on all of the pixels of the rectangle
+  * 2-Invert. This inverts all of the pixels of the rectangle
+  * 3-Black border. Draws a black perimeter not changing the inside
+  * 4-White border. Draws a white perimeter not changing the inside
+  * 5-Inverted border. Draws an inverted perimeter not changing the inside
+  * 6-Black border, White inside.
+  * 7-Black border, Inverted inside.
+  * 8-White border, Black inside.
+  * 9-White border, Inverted inside.
+  * 10-Shifts the contents in that rectangle up
+  * 11-Shifts the contents in that rectangle down
+  * 12-
+  * 13-
+  * 14-Pxl-Test Rect (count the number of ON pixels in the rectangle)
+  * 15-Pxl-Test Border (count the number of ON pixels on the border)
+  * 16-Inverted border, black fill
+  * 17-Inverted border, white fill
+
+## Line
+*Unfortunately, you use `Line(` to draw rectangles. The excuse for this is that
+when I very first made Grammer 1, I didn't think I'd ever have a line drawing
+routine, but I had rectangles galore. Without forethought, I decided using the
+`Line(` token was quite reasonable. I was wrong.*
+
+This is used to draw lines. The syntax for this command is
+`Line('x1,y1,x2,y2[,Method[,Buffer`
+
+So it is two sets of pixel coordinates and then the Method:
+* 0=White
+* 1=Black (Default)
+* 2=Invert
+
+`Buffer` is the buffer to draw to. It defaults to the current buffer.
+
+
+## Circle
+The syntax is `Circle(Y,X,R[,Method[,pattern[,buffer`.
+This draws a circle using Y and X as pixel coordinates and R as the radius of the circle in pixels. `Method` is how to draw the circle:
+* 1 - Black border (Default)
+* 2 - White border
+* 3 - Inverted border
+* 4 - White border, white fill
+* 5 - Black border, black fill
+* 6 - Invert border, invert fill
+* 7 - White border, black fill
+* 8 - White border, invert fill
+* 9 - Black border, white fill
+* 10 - Black border, invert fill
+* 11 - Invert border, white fill
+* 12 - Invert border, black fill
+
+
+`Pattern` is a number from 0 to 255 that will be used as a drawing pattern for the border. For example, 85 is `01010101` in binary, so every other pixel will not be drawn. Use 0 for no pattern. If the bit is 0, the pixel will be drawn, if it is 1, it won't be drawn. `Buffer` is the buffer to draw to (useful with grayscale).
+
+For basic usage:
+```
+.0:Return
+Circle(32,48,20
+DispGraph
+Stop
+```
+*![Image Description: A black circle of radius 20 pixels is drawn at the center of the screen.](https://i.imgur.com/s6WnO6N.png)*
+
+Or an example using a pattern, we need to include the method argument.
+```
+.0:Return
+Circle(32,48,20,1,85
+DispGraph
+Stop
+```
+*![Image Description: A black circle of radius 20 pixels is drawn at the center of the screen. Dotted every-other pixel.](https://i.imgur.com/VWdzeX0.png)*
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Sprites
+`Pt-Off(` is used to draw sprites to pixel coordinates. It is limited in some ways, compared to the Pt-On( command, but more flexible in others. The syntax is: `Pt-Off(Method,DataPointer,Y,X,[Width,[Height[,Buffer`
+
+* Method is how the sprite is drawn:
+  * 0-Overwrite
+    * This overwrites the graph screen data this is drawn to.
+  * 1-AND
+    * This draws the sprite with AND logic
+  * 2-XOR
+    * This draws the sprite with XOR logic
+  * 3-OR
+    * This draws the sprite with OR logic
+  * 5-Erase
+    * Where there are normally pixels on for the sprite, this
+  draws them as pixels off.
+  *By adding 8 to the Method, the data will be read as hexadecimal
+
+* DataPointer is a pointer to the sprite data
+* Y is the pixel Y-coordinate
+* X is the pixel X-coordinate
+* Width is the width of the sprite (in bytes). The default is 1 (8 pixels).
+* Height is the number of pixels tall the sprite is. 8 is default
+
+## Tiles
+`Pt-On(` also draws sprites, but only to 12 columns (every 8 pixels).
+This is slightly faster than `Pt-Off(` and has the advantage of
+variable width. It also has the DataSwap option that isn't present
+with the `Pt-Off(` command. Here is the syntax of the command:
+`Pt-On(Method,DataPointer,Y,X,[Width,[Height[,Buffer`
+
+* Method-This is how the sprite is drawn:
+  * 0-Overwrite
+  * 1-AND
+  * 2-XOR
+  * 3-OR
+  * 4-DataSwap
+    * This swaps the data on the graph screen with the sprite data. Doing this twice results in no change.
+  * 5-Erase
+  * 6-Mask
+    * This will display a masked sprite.
+  * 7-Gray
+    * This draws a frame of a 3 level gray sprite
+  *By adding 8 to the Method, the data will be read as hexadecimal
+* DataPointer is a pointer to the sprite data
+* Y is the pixel Y-coordinate
+* X is a value from 0 to 11.
+* Width is how wide the sprite is. 1=8 pixels, 2=16 pixels,.... Default is 1.
+* Height is the number of pixels tall the sprite is. Default is 8.
+
+## Tilemap
+`Pt-Change(` command is used to draw tilemaps.
+
+### Tilemap Method 0
+
+`Pt-Change(0,MapData,TileData,MapWidth,MapXOffset,MapYOffset,TileMethod`
+* MapData is a pointer to the map data
+* TileData is a pointer to the tile set
+* MapWidth is the width of the map (at least 12)
+* MapXOffset is the X offset into the map data
+* MapYOffset is the Y offset into the map data
+* TileMethod is how the sprite will be drawn (see Pt-On()
+
+Please note that the tile data and map data have to be raw bytes, as opposed to hexadecimal. There are some tools written in Grammer for creating sprite sets and tilemaps on TICalc or Omnimaga.
+
+### Smooth Scrolling Tilemap
+This is new in version 2.50.9.1.
+
+#### Init
+In order for smooth scrolling to be fast, Grammer needs to pre-compute a bunch
+of values. You must ***initialize*** the tilemap:
+```
+TileMap(1,tilemap,sprite_sheet,map_height,map_width[,buffer
+  tilemap - points to the tilemap (organized in rows)
+  sprite_sheet - points to an array of sprites
+  map_height - is the height of the map in tiles
+  map_width - is the width of the map in tiles
+  buffer - is an optional argument. Defaults to the current buffer.
+```
+***NOTE:** The tilemap data is set up differently from the original method! This
+map data is organized in such a way that is compatible with most map editors,
+so organized by row.*
+
+***NOTE:** The `buffer` argument assigns a buffer for the tilemap and is
+independent of the default buffer. When you render the tilemap, it ignores what
+the default buffer is, instead using the assigned tilemap buffer.*
+
+***NOTE:** This command does not draw anything! It just sets up pointers. See
+[Full Render](#full-render) to actually draw anything.*
+#### Full Render
+After a tilemap is initialized, you'll probably want to draw the starting map.
+This routine will render the tilemap to the tilemap buffer.
+
+Syntax is `TileMap(2[,y[,x`. This has an optional `y` and `x` argument that
+refer to the upper-left tile. Default is (0,0). For example, if you want to
+start 1 row and 1 column into the map data, you could do: `TileMap(2,1,1`.
+
+#### Scrolling
+Now that you have the map initialized and rendered, you can start scrolling!
+To scroll, you supply a direction and a number of pixels to scroll by. These
+routines will scroll the screen, scrolling in the new data. Available commands:
+- `TileMap(3,#` - shift down
+- `TileMap(4,#` - shift left
+- `TileMap(5,#` - shift right
+- `TileMap(6,#` - shift up
+- `Tilemap(7,dir,#` - shift in a combined direction:
+  - `dir` is 1 for down, 2 for left, 4 for right, 8 for up. To shift up+left,
+  you can use a `dir` of 8+2 = 10.
+
+An easy way to remember the order of the directions is that the follow the order
+of the getKey codes.
+
+#### Get Tile, Set Tile
+You can read a tile number based on its map coordinates, or set a tile based on
+its map coordinates. As well, you can get a tile number based on the pixel
+coordinates on the screen.
+- `TileMap(8,y,x` - read a tile
+- `TileMap(9,y,x,#` - set a tile to a new value, returns the old value
+- `TileMap(10,y,x` - read a tile based on pixel coordinates.
+
+#### Example Time

+ 6 - 0
docs/tutorials/img/optimize

@@ -0,0 +1,6 @@
+gifsicle -b -O3 *.gif
+mkdir img2
+pngcrush -d img2 *.png
+rm *.png
+mv img2/*.png ../img
+rmdir img2