css Audio - Active file-generic CSS - Active Generic - Active HTML - Active JS - Active SVG - Active Text - Active file-generic Video - Active header Love html icon-new-collection icon-person icon-team numbered-list123 pop-out spinner split-screen star tv

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              
body { margin: 0; overflow: hidden; background: #111; color: #ccc; }
#canvas {
  position: fixed;
  top:50%;
  bottom: 0;
  left: 50%;
  right: 0;

  width: 100vmin;
  height: 100vmin;

  transform:translate(-50%, -25%);

  image-rendering: optimizeSpeed;
  image-rendering: -moz-crisp-edges;
  image-rendering: -webkit-optimize-contrast;
  image-rendering: -o-crisp-edges;
  image-rendering: pixelated;
  -ms-interpolation-mode: nearest-neighbor;

  cursor: none;

  margin: auto;


}

//ctx.canvas.style = 'position:fixed; top: 50%; left:50%;width:!00vmin;height:100vmin;transform:translate(-50%, -50%)';

            
          
!
            
              var GAME = (function(){
 var states = {};

assets = {
  //font:{
//     string: "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_!@.'\"?/<()",
//     bin: [
//       ["111111111011111111001111111111111111000111111111111000110000100011000101110111100111011110011111111110001100011000110001100011111100100011101111010010111110111111111011100111001110000000010011111010100000000110110110111000001000100001001000"],
//       ["100011000110000100101000010000100001000100100000101001010000110111100110001100011000110001100000010010001100011000101010010100001001100100010000110010100001000000001100011000110001000000010010001111110000000010010011000100010001000010000100"],
//       ["111111111010000100011110011100101111111100100000101110010000101011010110001100101000111110011100010010001100011010100100001000010000100000100011011111111101111000010011100111110001000000010010111010100000000100100100011000100010000010000100"],
//       ["100011000110000100011000010000100011000100100100101001010000100011001110001111001001010001000010010010001010101010101010001000100000100001000000100010000011000100100100010000110001000000000010101111110000000000000000000001000001000010000100"],
//       ["100011111001111111101111110000111111000111111111101000111111100011000101110100000111110001111100010001110001000111010001001001111101110111111111000010111100111000100011100111001110111110010010111010100010000000000000010010000000100001001000"]
// ],
//  },
song: {
  songData: [
      { // Instrument 0
        i: [
        1, // OSC1_WAVEFORM
        192, // OSC1_VOL
        128, // OSC1_SEMI
        0, // OSC1_XENV
        1, // OSC2_WAVEFORM
        191, // OSC2_VOL
        116, // OSC2_SEMI
        9, // OSC2_DETUNE
        0, // OSC2_XENV
        0, // NOISE_VOL
        6, // ENV_ATTACK
        22, // ENV_SUSTAIN
        34, // ENV_RELEASE
        0, // ARP_CHORD
        0, // ARP_SPEED
        0, // LFO_WAVEFORM
        69, // LFO_AMT
        3, // LFO_FREQ
        1, // LFO_FX_FREQ
        1, // FX_FILTER
        23, // FX_FREQ
        167, // FX_RESONANCE
        0, // FX_DIST
        32, // FX_DRIVE
        77, // FX_PAN_AMT
        6, // FX_PAN_FREQ
        25, // FX_DELAY_AMT
        6 // FX_DELAY_TIME
        ],
        // Patterns
        p: [1],
        // Columns
        c: [
          {n: [159],
           f: []}
        ]
      },
      { // Instrument 1
        i: [
        2, // OSC1_WAVEFORM
        100, // OSC1_VOL
        128, // OSC1_SEMI
        0, // OSC1_XENV
        3, // OSC2_WAVEFORM
        201, // OSC2_VOL
        128, // OSC2_SEMI
        0, // OSC2_DETUNE
        0, // OSC2_XENV
        0, // NOISE_VOL
        5, // ENV_ATTACK
        6, // ENV_SUSTAIN
        58, // ENV_RELEASE
        0, // ARP_CHORD
        0, // ARP_SPEED
        0, // LFO_WAVEFORM
        195, // LFO_AMT
        6, // LFO_FREQ
        1, // LFO_FX_FREQ
        2, // FX_FILTER
        135, // FX_FREQ
        0, // FX_RESONANCE
        0, // FX_DIST
        32, // FX_DRIVE
        147, // FX_PAN_AMT
        6, // FX_PAN_FREQ
        121, // FX_DELAY_AMT
        6 // FX_DELAY_TIME
        ],
        // Patterns
        p: [],
        // Columns
        c: [
        ]
      },
      { // Instrument 2
        i: [
        2, // OSC1_WAVEFORM
        100, // OSC1_VOL
        128, // OSC1_SEMI
        0, // OSC1_XENV
        3, // OSC2_WAVEFORM
        201, // OSC2_VOL
        128, // OSC2_SEMI
        0, // OSC2_DETUNE
        0, // OSC2_XENV
        0, // NOISE_VOL
        5, // ENV_ATTACK
        6, // ENV_SUSTAIN
        58, // ENV_RELEASE
        0, // ARP_CHORD
        0, // ARP_SPEED
        0, // LFO_WAVEFORM
        195, // LFO_AMT
        6, // LFO_FREQ
        1, // LFO_FX_FREQ
        2, // FX_FILTER
        135, // FX_FREQ
        0, // FX_RESONANCE
        0, // FX_DIST
        32, // FX_DRIVE
        147, // FX_PAN_AMT
        6, // FX_PAN_FREQ
        121, // FX_DELAY_AMT
        6 // FX_DELAY_TIME
        ],
        // Patterns
        p: [],
        // Columns
        c: [
        ]
      },
      { // Instrument 3
        i: [
        2, // OSC1_WAVEFORM
        100, // OSC1_VOL
        128, // OSC1_SEMI
        0, // OSC1_XENV
        3, // OSC2_WAVEFORM
        201, // OSC2_VOL
        128, // OSC2_SEMI
        0, // OSC2_DETUNE
        0, // OSC2_XENV
        0, // NOISE_VOL
        5, // ENV_ATTACK
        6, // ENV_SUSTAIN
        58, // ENV_RELEASE
        0, // ARP_CHORD
        0, // ARP_SPEED
        0, // LFO_WAVEFORM
        195, // LFO_AMT
        6, // LFO_FREQ
        1, // LFO_FX_FREQ
        2, // FX_FILTER
        135, // FX_FREQ
        0, // FX_RESONANCE
        0, // FX_DIST
        32, // FX_DRIVE
        147, // FX_PAN_AMT
        6, // FX_PAN_FREQ
        121, // FX_DELAY_AMT
        6 // FX_DELAY_TIME
        ],
        // Patterns
        p: [],
        // Columns
        c: [
        ]
      },
      { // Instrument 4
        i: [
        2, // OSC1_WAVEFORM
        100, // OSC1_VOL
        128, // OSC1_SEMI
        0, // OSC1_XENV
        3, // OSC2_WAVEFORM
        201, // OSC2_VOL
        128, // OSC2_SEMI
        0, // OSC2_DETUNE
        0, // OSC2_XENV
        0, // NOISE_VOL
        5, // ENV_ATTACK
        6, // ENV_SUSTAIN
        58, // ENV_RELEASE
        0, // ARP_CHORD
        0, // ARP_SPEED
        0, // LFO_WAVEFORM
        195, // LFO_AMT
        6, // LFO_FREQ
        1, // LFO_FX_FREQ
        2, // FX_FILTER
        135, // FX_FREQ
        0, // FX_RESONANCE
        0, // FX_DIST
        32, // FX_DRIVE
        147, // FX_PAN_AMT
        6, // FX_PAN_FREQ
        121, // FX_DELAY_AMT
        6 // FX_DELAY_TIME
        ],
        // Patterns
        p: [],
        // Columns
        c: [
        ]
      },
      { // Instrument 5
        i: [
        2, // OSC1_WAVEFORM
        100, // OSC1_VOL
        128, // OSC1_SEMI
        0, // OSC1_XENV
        3, // OSC2_WAVEFORM
        201, // OSC2_VOL
        128, // OSC2_SEMI
        0, // OSC2_DETUNE
        0, // OSC2_XENV
        0, // NOISE_VOL
        5, // ENV_ATTACK
        6, // ENV_SUSTAIN
        58, // ENV_RELEASE
        0, // ARP_CHORD
        0, // ARP_SPEED
        0, // LFO_WAVEFORM
        195, // LFO_AMT
        6, // LFO_FREQ
        1, // LFO_FX_FREQ
        2, // FX_FILTER
        135, // FX_FREQ
        0, // FX_RESONANCE
        0, // FX_DIST
        32, // FX_DRIVE
        147, // FX_PAN_AMT
        6, // FX_PAN_FREQ
        121, // FX_DELAY_AMT
        6 // FX_DELAY_TIME
        ],
        // Patterns
        p: [],
        // Columns
        c: [
        ]
      },
      { // Instrument 6
        i: [
        2, // OSC1_WAVEFORM
        100, // OSC1_VOL
        128, // OSC1_SEMI
        0, // OSC1_XENV
        3, // OSC2_WAVEFORM
        201, // OSC2_VOL
        128, // OSC2_SEMI
        0, // OSC2_DETUNE
        0, // OSC2_XENV
        0, // NOISE_VOL
        5, // ENV_ATTACK
        6, // ENV_SUSTAIN
        58, // ENV_RELEASE
        0, // ARP_CHORD
        0, // ARP_SPEED
        0, // LFO_WAVEFORM
        195, // LFO_AMT
        6, // LFO_FREQ
        1, // LFO_FX_FREQ
        2, // FX_FILTER
        135, // FX_FREQ
        0, // FX_RESONANCE
        0, // FX_DIST
        32, // FX_DRIVE
        147, // FX_PAN_AMT
        6, // FX_PAN_FREQ
        121, // FX_DELAY_AMT
        6 // FX_DELAY_TIME
        ],
        // Patterns
        p: [],
        // Columns
        c: [
        ]
      },
      { // Instrument 7
        i: [
        2, // OSC1_WAVEFORM
        100, // OSC1_VOL
        128, // OSC1_SEMI
        0, // OSC1_XENV
        3, // OSC2_WAVEFORM
        201, // OSC2_VOL
        128, // OSC2_SEMI
        0, // OSC2_DETUNE
        0, // OSC2_XENV
        0, // NOISE_VOL
        5, // ENV_ATTACK
        6, // ENV_SUSTAIN
        58, // ENV_RELEASE
        0, // ARP_CHORD
        0, // ARP_SPEED
        0, // LFO_WAVEFORM
        195, // LFO_AMT
        6, // LFO_FREQ
        1, // LFO_FX_FREQ
        2, // FX_FILTER
        135, // FX_FREQ
        0, // FX_RESONANCE
        0, // FX_DIST
        32, // FX_DRIVE
        147, // FX_PAN_AMT
        6, // FX_PAN_FREQ
        121, // FX_DELAY_AMT
        6 // FX_DELAY_TIME
        ],
        // Patterns
        p: [],
        // Columns
        c: [
        ]
      }
    ],
    rowLen: 5513,   // In sample lengths
    patternLen: 1,  // Rows per pattern
    endPattern: 2  // End pattern
},
songdemo: {
  songData: [
        { // Instrument 0
          i: [
          2, // OSC1_WAVEFORM
          159, // OSC1_VOL
          128, // OSC1_SEMI
          0, // OSC1_XENV
          3, // OSC2_WAVEFORM
          201, // OSC2_VOL
          128, // OSC2_SEMI
          4, // OSC2_DETUNE
          0, // OSC2_XENV
          0, // NOISE_VOL
          0, // ENV_ATTACK
          21, // ENV_SUSTAIN
          33, // ENV_RELEASE
          0, // ARP_CHORD
          0, // ARP_SPEED
          2, // LFO_WAVEFORM
          232, // LFO_AMT
          3, // LFO_FREQ
          1, // LFO_FX_FREQ
          3, // FX_FILTER
          50, // FX_FREQ
          210, // FX_RESONANCE
          149, // FX_DIST
          244, // FX_DRIVE
          156, // FX_PAN_AMT
          6, // FX_PAN_FREQ
          123, // FX_DELAY_AMT
          6 // FX_DELAY_TIME
          ],
          // Patterns
          p: [1,1,1,1,4,4,2,3,1,1,2,3,4,4,2,3,1,1,2,3,4,4,4,4,4,4,5,4,5,1,5,4,4,2,3,6],
          // Columns
          c: [
            {n: [120,120,132,120,132,120,130,132,120,120,132,120,132,120,130,132,120,120,132,120,132,120,130,132,120,120,132,120,132,120,130,132],
             f: [13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,33]},
            {n: [118,118,130,118,130,118,128,130,118,118,130,118,130,118,128,130,118,118,130,118,130,118,128,130,118,118,130,118,130,118,128,130],
             f: []},
            {n: [113,113,125,113,125,113,123,125,113,113,125,113,125,113,123,125,113,113,125,113,125,113,123,125,113,113,125,113,125,113,123,125],
             f: []},
            {n: [120,120,132,120,132,120,130,132,120,120,132,120,132,120,130,132,120,120,132,120,132,120,130,132,120,120,132,120,132,120,130,132],
             f: [13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,43]},
            {n: [118,118,130,118,130,118,128,130,118,118,130,118,130,118,128,130,113,113,125,113,125,113,123,125,113,113,125,113,125,113,123,125],
             f: []},
            {n: [120,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,127],
             f: [13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,115]}
          ]
        },
        { // Instrument 1
          i: [
          0, // OSC1_WAVEFORM
          128, // OSC1_VOL
          106, // OSC1_SEMI
          1, // OSC1_XENV
          0, // OSC2_WAVEFORM
          127, // OSC2_VOL
          106, // OSC2_SEMI
          12, // OSC2_DETUNE
          1, // OSC2_XENV
          16, // NOISE_VOL
          0, // ENV_ATTACK
          0, // ENV_SUSTAIN
          191, // ENV_RELEASE
          0, // ARP_CHORD
          0, // ARP_SPEED
          0, // LFO_WAVEFORM
          0, // LFO_AMT
          0, // LFO_FREQ
          0, // LFO_FX_FREQ
          2, // FX_FILTER
          24, // FX_FREQ
          169, // FX_RESONANCE
          5, // FX_DIST
          71, // FX_DRIVE
          83, // FX_PAN_AMT
          5, // FX_PAN_FREQ
          0, // FX_DELAY_AMT
          0 // FX_DELAY_TIME
          ],
          // Patterns
          p: [,,,,1,1,1,1,1,1,1,1,1,1,1,1,,,,,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2],
          // Columns
          c: [
            {n: [135,,,135,,,135,,135,,,135,,,135,,135,,,135,,,135,,135,,,135,,,135],
             f: [13,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,138,56]},
            {n: [135],
             f: [13,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,,164,,,,,,,,,,,191]}
          ]
        },
        { // Instrument 2
          i: [
          0, // OSC1_WAVEFORM
          107, // OSC1_VOL
          128, // OSC1_SEMI
          0, // OSC1_XENV
          0, // OSC2_WAVEFORM
          7, // OSC2_VOL
          128, // OSC2_SEMI
          0, // OSC2_DETUNE
          1, // OSC2_XENV
          0, // NOISE_VOL
          109, // ENV_ATTACK
          27, // ENV_SUSTAIN
          208, // ENV_RELEASE
          0, // ARP_CHORD
          0, // ARP_SPEED
          3, // LFO_WAVEFORM
          236, // LFO_AMT
          9, // LFO_FREQ
          1, // LFO_FX_FREQ
          2, // FX_FILTER
          135, // FX_FREQ
          0, // FX_RESONANCE
          0, // FX_DIST
          11, // FX_DRIVE
          147, // FX_PAN_AMT
          6, // FX_PAN_FREQ
          152, // FX_DELAY_AMT
          3 // FX_DELAY_TIME
          ],
          // Patterns
          p: [,,2,,,2,,,,,3,,,2,,,1,2,3,4,,,2,,,2,,1,5,1,5],
          // Columns
          c: [
            {n: [156,,168],
             f: []},
            {n: [156,,163],
             f: []},
            {n: [154,,166],
             f: []},
            {n: [149,,161],
             f: []},
            {n: [154,,166,,,,,,,,,,,,,,149,,161],
             f: []}
          ]
        },
        { // Instrument 3
          i: [
          0, // OSC1_WAVEFORM
          0, // OSC1_VOL
          140, // OSC1_SEMI
          0, // OSC1_XENV
          0, // OSC2_WAVEFORM
          0, // OSC2_VOL
          140, // OSC2_SEMI
          0, // OSC2_DETUNE
          0, // OSC2_XENV
          255, // NOISE_VOL
          242, // ENV_ATTACK
          0, // ENV_SUSTAIN
          0, // ENV_RELEASE
          0, // ARP_CHORD
          0, // ARP_SPEED
          2, // LFO_WAVEFORM
          255, // LFO_AMT
          3, // LFO_FREQ
          1, // LFO_FX_FREQ
          2, // FX_FILTER
          77, // FX_FREQ
          231, // FX_RESONANCE
          0, // FX_DIST
          32, // FX_DRIVE
          243, // FX_PAN_AMT
          3, // FX_PAN_FREQ
          157, // FX_DELAY_AMT
          2 // FX_DELAY_TIME
          ],
          // Patterns
          p: [,,,1,,,,1,,,,1,,,,1,,,,1,,,,1,,,1,,,,1,,,,1],
          // Columns
          c: [
            {n: [147],
             f: []}
          ]
        },
        { // Instrument 4
          i: [
          3, // OSC1_WAVEFORM
          0, // OSC1_VOL
          128, // OSC1_SEMI
          0, // OSC1_XENV
          0, // OSC2_WAVEFORM
          0, // OSC2_VOL
          128, // OSC2_SEMI
          3, // OSC2_DETUNE
          0, // OSC2_XENV
          255, // NOISE_VOL
          0, // ENV_ATTACK
          0, // ENV_SUSTAIN
          142, // ENV_RELEASE
          0, // ARP_CHORD
          0, // ARP_SPEED
          0, // LFO_WAVEFORM
          0, // LFO_AMT
          0, // LFO_FREQ
          0, // LFO_FX_FREQ
          2, // FX_FILTER
          21, // FX_FREQ
          226, // FX_RESONANCE
          104, // FX_DIST
          255, // FX_DRIVE
          105, // FX_PAN_AMT
          4, // FX_PAN_FREQ
          105, // FX_DELAY_AMT
          4 // FX_DELAY_TIME
          ],
          // Patterns
          p: [,,,,2,,,,,,,,3,1,1,1,,,,,,,,,1,1,1,1,1,1,1,1,1,1,1,2],
          // Columns
          c: [
            {n: [,,,,147,,,,,,,,147,,,,,,,,147,,,,,,,,147],
             f: [13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,65]},
            {n: [147],
             f: [13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,142]},
            {n: [147,,,,,,,,,,,,147,,,,,,,,147,,,,,,,,147],
             f: [13,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,142,65]}
          ]
        },
        { // Instrument 5
          i: [
          0, // OSC1_WAVEFORM
          192, // OSC1_VOL
          104, // OSC1_SEMI
          0, // OSC1_XENV
          0, // OSC2_WAVEFORM
          192, // OSC2_VOL
          116, // OSC2_SEMI
          4, // OSC2_DETUNE
          0, // OSC2_XENV
          0, // NOISE_VOL
          5, // ENV_ATTACK
          17, // ENV_SUSTAIN
          56, // ENV_RELEASE
          0, // ARP_CHORD
          0, // ARP_SPEED
          0, // LFO_WAVEFORM
          69, // LFO_AMT
          5, // LFO_FREQ
          1, // LFO_FX_FREQ
          3, // FX_FILTER
          82, // FX_FREQ
          181, // FX_RESONANCE
          13, // FX_DIST
          187, // FX_DRIVE
          148, // FX_PAN_AMT
          5, // FX_PAN_FREQ
          128, // FX_DELAY_AMT
          8 // FX_DELAY_TIME
          ],
          // Patterns
          p: [,,,,,,,,1,1,2,3,1,1,2,3,1,1,2,3,,,1,1,,,,1,4,1,4],
          // Columns
          c: [
            {n: [144,,,144,,144,142,156,,,,,,,,,144,,,144,,144,142,156],
             f: []},
            {n: [142,,,142,,142,140,154,,,,,,,,,142,,,142,,142,140,154],
             f: []},
            {n: [149,,,149,,149,147,161,,,,,,,,,149,,,149,,149,147,161],
             f: []},
            {n: [142,,,142,,142,140,154,,,,,,,,,149,,,149,,149,147,161],
             f: []}
          ]
        },
        { // Instrument 6
          i: [
          0, // OSC1_WAVEFORM
          131, // OSC1_VOL
          116, // OSC1_SEMI
          0, // OSC1_XENV
          0, // OSC2_WAVEFORM
          117, // OSC2_VOL
          140, // OSC2_SEMI
          2, // OSC2_DETUNE
          0, // OSC2_XENV
          0, // NOISE_VOL
          120, // ENV_ATTACK
          6, // ENV_SUSTAIN
          47, // ENV_RELEASE
          0, // ARP_CHORD
          0, // ARP_SPEED
          0, // LFO_WAVEFORM
          39, // LFO_AMT
          8, // LFO_FREQ
          0, // LFO_FX_FREQ
          2, // FX_FILTER
          255, // FX_FREQ
          0, // FX_RESONANCE
          18, // FX_DIST
          35, // FX_DRIVE
          75, // FX_PAN_AMT
          5, // FX_PAN_FREQ
          108, // FX_DELAY_AMT
          2 // FX_DELAY_TIME
          ],
          // Patterns
          p: [,,,,,,,,,,,,,,,,,,,,,,,,1,2,1,2,3,2,3,2],
          // Columns
          c: [
            {n: [151,149,147,144,,,,,,,144,,147,151,,149,,,,,,,,,149,151,154,149,151,154,151,154],
             f: [11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19]},
            {n: [156],
             f: [11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,120]},
            {n: [151,149,151,154,,,,,,,156,,154,151,,149,,,,,,,,,149,151,154,149,151,154,151,154],
             f: [11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19]}
          ]
        },
        { // Instrument 7
          i: [
          3, // OSC1_WAVEFORM
          100, // OSC1_VOL
          128, // OSC1_SEMI
          0, // OSC1_XENV
          3, // OSC2_WAVEFORM
          201, // OSC2_VOL
          128, // OSC2_SEMI
          3, // OSC2_DETUNE
          0, // OSC2_XENV
          0, // NOISE_VOL
          135, // ENV_ATTACK
          0, // ENV_SUSTAIN
          100, // ENV_RELEASE
          0, // ARP_CHORD
          0, // ARP_SPEED
          0, // LFO_WAVEFORM
          81, // LFO_AMT
          6, // LFO_FREQ
          1, // LFO_FX_FREQ
          3, // FX_FILTER
          111, // FX_FREQ
          165, // FX_RESONANCE
          5, // FX_DIST
          19, // FX_DRIVE
          147, // FX_PAN_AMT
          5, // FX_PAN_FREQ
          162, // FX_DELAY_AMT
          3 // FX_DELAY_TIME
          ],
          // Patterns
          p: [,,,,,,,,,,,,,,,,,,,,1,2,1,2,1,2,3,2,3,2,3,2],
          // Columns
          c: [
            {n: [159,156,,,,,,,,,,,,,,,161,156],
             f: []},
            {n: [163,156,,,,,,,,,,,,,,,163,156],
             f: []},
            {n: [159,154,,,,,,,,,,,,,,,161,156],
             f: []}
          ]
        }
      ],
      rowLen: 7350,   // In sample lengths
      patternLen: 32,  // Rows per pattern
      endPattern: 37  // End pattern
},

  letters: {
            '-' : [
                [,,,,0],
                [,,,,0],
                [1,1,1,1,1],
                [,,,,0],
                [,,,,0]

            ],
            '.' : [
                [,,,,0],
                [,,,,0],
                [,,,,0],
                [,,,,0],
                [,,1,,0]

            ],
            '1': [
                [,1,1,,0],
                [,,1,,0],
                [,,1,,0],
                [,,1,,0],
                [1,1,1,1,1]

            ],
            '2': [
                [1, 1, 1, 1, 0],
                [, , , , 1],
                [, 1, 1, 1, 0],
                [1, , , , 0],
                [1, 1, 1, 1, 1]
            ],
            '3': [
                [1, 1, 1, 1, 0],
                [, , , , 1],
                [, 1, 1, 1, 1],
                [, , , , 1],
                [1, 1, 1, 1, 0]
            ],
            '4': [
                [1, , , 1, 0],
                [1, , , 1, 0],
                [1, 1, 1, 1, 1],
                [, , , 1, 0],
                [, , , 1, 0]
            ],
            '5': [
                [1, 1, 1, 1, 1],
                [1, , , , 0],
                [1, 1, 1, 1, 0],
                [, , , , 1],
                [1, 1, 1, 1, 0]
            ],
            '6': [
                [, 1, 1, 1, 0],
                [1, , , , 0],
                [1, 1, 1, 1, 0],
                [1, , , , 1],
                [, 1, 1, 1, 0]
            ],
            '7': [
                [1, 1, 1, 1, 1],
                [, , , , 1],
                [, , , 1, 0],
                [, , 1, , 0],
                [, , 1, , 0]
            ],
            '8': [
                [, 1, 1, 1, 0],
                [1, , , , 1],
                [, 1, 1, 1, 0],
                [1, , , , 1],
                [, 1, 1, 1, 0]
            ],
            '9': [
                [, 1, 1, 1, 0],
                [1, , , , 1],
                [, 1, 1, 1, 1],
                [, , , , 1],
                [, 1, 1, 1, 0]
            ],
            '0': [
                [, 1, 1, 1, 0],
                [1, , , , 1],
                [1, , , , 1],
                [1, , , , 1],
                [, 1, 1, 1, 0]
            ],
            'A': [
                [1, 1, 1, 1, 1],
                [1, , , , 1],
                [1, 1, 1, 1, 1],
                [1, , , , 1],
                [1, , , , 1]
            ],
            'B': [
                [1, 1, 1, 1, 0],
                [1, , , 1, 0],
                [1, 1, 1, 1, 1],
                [1, , , , 1],
                [1, 1, 1, 1, 1]
            ],
            'C': [
                [1, 1, 1, 1, 1],
                [1, , , , 0],
                [1, , , , 0],
                [1, , , , 0],
                [1, 1, 1, 1, 1]
            ],
            'D': [
                [1, 1, 1, , 0],
                [1, , , 1, 0],
                [1, , , , 1],
                [1, , , , 1],
                [1, 1, 1, 1, 1]
            ],
            'E': [
                [1, 1, 1, 1, 1],
                [1, , , , 0],
                [1, 1, 1, , 0],
                [1, , , , 0],
                [1, 1, 1, 1, 1]
            ],
            'F': [
                [1, 1, 1, 1, 1],
                [1, , , , 0],
                [1, 1, 1, , 0],
                [1, , , , 0],
                [1, , , , 0]
            ],
            'G': [
                [1, 1, 1, 1, 1],
                [1, , , , 0],
                [1, , 1, 1, 1],
                [1, , , , 1],
                [1, 1, 1, 1, 1]
            ],
            'H': [
                [1, , , , 1],
                [1, , , , 1],
                [1, 1, 1, 1, 1],
                [1, , , , 1],
                [1, , , , 1]
            ],
            'I': [
                [1, 1, 1, 1, 1],
                [, , 1, , 0],
                [, , 1, , 0],
                [, , 1, , 0],
                [1, 1, 1, 1, 1]
            ],
            'J': [
                [, , , , 1],
                [, , , , 1],
                [, , , , 1],
                [1, , , , 1],
                [1, 1, 1, 1, 1]
            ],
            'K': [
                [1, , , 1, 0],
                [1, , 1, , 0],
                [1, 1, 1, , 0],
                [1, , , 1, 0],
                [1, , , , 1]
            ],
            'L': [
                [1, , , , 0],
                [1, , , , 0],
                [1, , , , 0],
                [1, , , , 0],
                [1, 1, 1, 1, 1]
            ],
            'M': [
                [1, , , , 1],
                [1, 1, , 1, 1],
                [1, , 1, , 1],
                [1, , , , 1],
                [1, , , , 1]
            ],
            'N': [
                [1, , , , 1],
                [1, 1, , , 1],
                [1, , 1, , 1],
                [1, , , 1, 1],
                [1, , , , 1]
            ],
            'O': [
                [1, 1, 1, 1, 1],
                [1, , , , 1],
                [1, , , , 1],
                [1, , , , 1],
                [1, 1, 1, 1, 1]
            ],
            'P': [
                [1, 1, 1, 1, 1],
                [1, , , , 1],
                [1, 1, 1, 1, 1],
                [1, , , , 0],
                [1, , , , 0]
            ],
            'Q': [
                [1, 1, 1, 1, 0],
                [1, , , 1, 0],
                [1, , , 1, 0],
                [1, , , 1, 0],
                [1, 1, 1, 1, 1]
            ],
            'R': [
                [1, 1, 1, 1, 1],
                [1, , , , 1],
                [1, 1, 1, 1, 1],
                [1, , , 1, 0],
                [1, , , , 1]
            ],
            'S': [
                [1, 1, 1, 1, 1],
                [1, , , , 0],
                [1, 1, 1, 1, 1],
                [, , , , 1],
                [1, 1, 1, 1, 1]
            ],
            'T': [
                [1, 1, 1, 1, 1],
                [, , 1, , 0],
                [, , 1, , 0],
                [, , 1, , 0],
                [, , 1, , 0]
            ],
            'U': [
                [1, , , , 1],
                [1, , , , 1],
                [1, , , , 1],
                [1, , , , 1],
                [1, 1, 1, 1, 1]
            ],
            'V': [
                [1, , , , 1],
                [1, , , , 1],
                [1, , , , 1],
                [, 1, , 1, 0],
                [, , 1, , 0]
            ],
            'W': [
                [1, , , , 1],
                [1, , , , 1],
                [1, , 1, , 1],
                [1, 1, , 1, 1],
                [1, , , , 1]
            ],
            'X': [
                [1, , , , 1],
                [, 1, , 1, 0],
                [, , 1, , 0],
                [, 1, , 1, 0],
                [1, , , , 1]
            ],
            'Y': [
                [1, , , , 1],
                [1, , , , 1],
                [1, 1, 1, 1, 1],
                [, , 1, , 0],
                [, , 1, , 0]
            ],
            'Z': [
                [1, 1, 1, 1, 1],
                [, , , 1, 0],
                [, , 1, , 0],
                [, 1, , , 0],
                [1, 1, 1, 1, 1]
            ],
            ' ': [
                [, , , , 0],
                [, , , , 0],
                [, , , , 0],
                [, , , , 0],
                [, , , , 0]
            ],
            ',': [
                [, , , , 0],
                [, , , , 0],
                [, , , , 0],
                [, , 1, , 0],
                [, , 1, , 0]
            ],
            '+': [
                [, , , , 0],
                [, , 1, , 0],
                [, 1, 1, 1, 0],
                [, , 1, , 0],
                [, , , , 0]
            ],
            '/': [
                [, , , , 1],
                [, , , 1, 0],
                [, , 1, , 0],
                [, 1, , , 0],
                [1, , , , 0]
            ],
            ':': [
                [, , , , 0],
                [, , 1, , 0],
                [, , , , 0],
                [, , 1, , 0],
                [, , , , 0]
            ],
            '@': [
                [1, 1, 1, 1, 1],
                [, , , , 1],
                [1, 1, 1, , 1],
                [1, , 1, , 1],
                [1, 1, 1, 1, 1]
            ],
            /*'x': [ //solid first checkers
                [1, , 1, , 1],
                [, 1, , 1, 0],
                [1, , 1, , 1],
                [, 1, , 1, 0],
                [1, , 1, , 1]
            ],
            'z': [
                //empty first checkers
                [, 1, , 1, 0],
                [1, , 1, , 1],
                [, 1, , 1, 0],
                [1, , 1, , 1],
                [, 1, , 1, 0]
            ],
            'o': [
                //box with dot
                [1, 1, 1, 1, 1],
                [1, , , , 1],
                [1, , 1, , 1],
                [1, , , , 1],
                [1, 1, 1, 1, 1]
            ],
            'e': [
                //down-right slope
                [1,,,,0],
                [1,1,,,0],
                [1,1,1,,0],
                [1,1,1,1,0],
                [1,1,1,1,1],

            ],
            'w': [
                //down-left slope
                [,,,,1],
                [,,,1,1],
                [,,1,1,1],
                [,1,1,1,1],
                [1,1,1,1,1],

            ],
            's': [
                //up-left slope
                [1, 1, 1, 1, 1],
                [, 1, 1, 1, 1],
                [, , 1, 1, 1],
                [, , , 1, 1],
                [, , , , 1]
            ],
            'd': [
                //up-right slope
                [1,1,1,1,1],
                [1,1,1,1,0],
                [1,1,1,,0],
                [1,1,,,0],
                [1,,,,0]

            ],
            't': [
                //player 1
                [0,0,0,1,1],
                [0,0,1,1,1],
                [0,0,1,1,1],
                [0,0,1,1,1],
                [0,0,1,1,1],

            ],
            'y': [
                //player 1
                [1,1,1,1,1],
                [1,1,1,1,1],
                [1,1,1,1,1],
                [1,1,1,1,1],
                [1,1,1,1,1]
            ],
            'u': [
                //player 1
                [1,1,0,0,0],
                [1,1,1,0,0],
                [0,0,1,0,0],
                [0,1,1,0,0],
                [1,1,1,0,0]
            ],
            'g': [
                //player 1
                [0,0,1,1,1],
                [0,0,0,1,1],
                [0,0,0,0,0],
                [0,0,0,0,0],
                [0,0,0,0,1]
            ],
            'h': [
                //player 1
                [1,1,1,1,1],
                [1,1,1,1,1],
                [0,1,1,1,0],
                [1,1,1,1,1],
                [1,1,1,1,1]
            ],
            'j': [
                //player 1
                [1,1,1,0,0],
                [1,1,0,0,0],
                [0,0,0,0,0],
                [0,0,0,0,0],
                [1,1,1,1,1]
            ],
            'b': [
                //player 1
                [0,0,0,1,1],
                [0,0,0,1,1],
                [0,0,0,0,1],
                [0,0,0,0,1],
                [0,0,0,0,1]
            ],
            'n': [
                //player 1
                [1,1,1,1,1],
                [1,1,1,1,1],
                [0,0,0,0,0],
                [0,0,0,0,0],
                [0,0,0,0,0],

            ],

            'a': [

                [1,1,1,1,1],
                [1,1,1,1,1],
                [1,1,1,1,1],
                [1,1,1,1,1],
                [1,1,1,1,1],

            ], */



        }
};

//--this gets wrapped in a closure, so no namespace object, compresses better.

var
C =               document.getElementById('canvas');
ctx =             C.getContext('2d'),

renderTarget =    0x00000,
renderSource =    0x10000,

//Richard Fhager's DB32 Palette http://http://pixeljoint.com/forum/forum_posts.asp?TID=16247
//ofcourse you can change this to whatever you like, up to 256 colors.
//one GOTCHA: colors are stored 0xAABBGGRR, so you'll have to flop the values from your typical hex colors.

colors =          [0xff000000, 0xff342022, 0xff3c2845, 0xff313966, 0xff3b568f, 0xff2671df, 0xff66a0d9, 0xff9ac3ee, 0xff36f2fb,
                   0xff50e599, 0xff30be6a, 0xff6e9437, 0xff2f694b, 0xff244b52, 0xff393c32, 0xff743f3f, 0xff826030, 0xffe16e5b,
                   0xffff9b63, 0xffe4cd5f, 0xfffcdbcb, 0xffffffff, 0xffb7ad9b, 0xff877e84, 0xff6a6a69, 0xff525659, 0xff8a4276,
                   0xff3232ac, 0xff6357d9, 0xffba7bd7, 0xff4a978f, 0xff306f8a],

//default palette index
palDefault =      [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31],

//active palette index. maps to indices in colors[]. can alter this whenever for palette effects.
pal =             [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31];

ctx.imageSmoothingEnabled = false;
ctx.mozImageSmoothingEnabled = false;

C.width = C.height = 256;
var imageData =       ctx.getImageData(0, 0, 256, 256),
buf =             new ArrayBuffer(imageData.data.length),
buf8 =            new Uint8Array(buf),
data =            new Uint32Array(buf),
ram =             new Uint8ClampedArray(0x80000);

//--------------graphics functions----------------
      function clear(color){
        ram.fill(color, renderTarget, renderTarget + 0x10000);
      }

      function pset(x, y, color) { //from colors array, 0-31
        x = x|0; y = y|0;

        if (x > -1 && x < 256 && y > -1 && y < 256) {
          ram[renderTarget + (y * 256 + x)] = color;
        }
      }

      function line(x1, y1, x2, y2, color) {

        x1 = x1|0;
        x2 = x2|0;
        y1 = y1|0;
        y2 = y2|0;

        var dy = (y2 - y1);
        var dx = (x2 - x1);
        var stepx, stepy;

        if (dy < 0) {
          dy = -dy;
          stepy = -1;
        } else {
          stepy = 1;
        }
        if (dx < 0) {
          dx = -dx;
          stepx = -1;
        } else {
          stepx = 1;
        }
        dy <<= 1;        // dy is now 2*dy
        dx <<= 1;        // dx is now 2*dx

        pset(x1, y1, color);
        if (dx > dy) {
          var fraction = dy - (dx >> 1);  // same as 2*dy - dx
          while (x1 != x2) {
            if (fraction >= 0) {
              y1 += stepy;
              fraction -= dx;          // same as fraction -= 2*dx
            }
            x1 += stepx;
            fraction += dy;              // same as fraction -= 2*dy
            pset(x1, y1, color);
          }
          ;
        } else {
          fraction = dx - (dy >> 1);
          while (y1 != y2) {
            if (fraction >= 0) {
              x1 += stepx;
              fraction -= dy;
            }
            y1 += stepy;
            fraction += dx;
            pset(x1, y1, color);
          }
        }

      }

      function circle(xm, ym, r, color) {
        var x = -r, y = 0, err = 2 - 2 * r;
        /* II. Quadrant */
        do {
          pset(xm - x, ym + y, color);
          /*   I. Quadrant */
          pset(xm - y, ym - x, color);
          /*  II. Quadrant */
          pset(xm + x, ym - y, color);
          /* III. Quadrant */
          pset(xm + y, ym + x, color);
          /*  IV. Quadrant */
          r = err;
          if (r <= y) err += ++y * 2 + 1;
          /* e_xy+e_y < 0 */
          if (r > x || err > y) err += ++x * 2 + 1;
          /* e_xy+e_x > 0 or no 2nd y-step */

        } while (x < 0);
      }

      function fillCircle(xm, ym, r, color) {
        if(r < 0) return;
        xm = xm|0; ym = ym|0, r = r|0; color = color|0;
        var x = -r, y = 0, err = 2 - 2 * r;
        /* II. Quadrant */
        do {
          line(xm-x, ym-y, xm+x, ym-y, color);
          line(xm-x, ym+y, xm+x, ym+y, color);
          r = err;
          if (r <= y) err += ++y * 2 + 1;
          if (r > x || err > y) err += ++x * 2 + 1;
        } while (x < 0);
      }

      function rect(x, y, w, h, color) {
        x1 = x|0;
        y1 = y|0;
        x2 = (x+w)|0;
        y2 = (y+h)|0;


        line(x1,y1, x2, y1, color);
        line(x2, y1, x2, y2, color);
        line(x1, y2, x2, y2, color);
        line(x1, y1, x1, y2, color);
      }

      function fr(x, y, w, h, color) {  //draw a filled rectangle

        x1 = x|0;
        y1 = y|0;
        x2 = (x+w)|0;
        y2 = (y+h)|0;

        var i = Math.abs(y2 - y1);
        line(x1, y1, x2, y1, color);

        if(i > 0){
          while (--i) {
            line(x1, y1+i, x2, y1+i, color);
          }
        }

        line(x1,y2, x2, y2, color);
      }

      function triangle(x1, y1, x2, y2, x3, y3, color) {
        line(x1,y1, x2,y2, color);
        line(x2,y2, x3,y3, color);
        line(x3,y3, x1,y1, color);
      }

      function fillTriangle( x1, y1, x2, y2, x3, y3, color ) {

        var canvasWidth = 256;
        // http://devmaster.net/forums/topic/1145-advanced-rasterization/
        // 28.4 fixed-point coordinates
        var x1 = Math.round( 16 * x1 );
        var x2 = Math.round( 16 * x2 );
        var x3 = Math.round( 16 * x3 );
        var y1 = Math.round( 16 * y1 );
        var y2 = Math.round( 16 * y2 );
        var y3 = Math.round( 16 * y3 );
        // Deltas
        var dx12 = x1 - x2, dy12 = y2 - y1;
        var dx23 = x2 - x3, dy23 = y3 - y2;
        var dx31 = x3 - x1, dy31 = y1 - y3;
        // Bounding rectangle
        var minx = Math.max( ( Math.min( x1, x2, x3 ) + 0xf ) >> 4, 0 );
        var maxx = Math.min( ( Math.max( x1, x2, x3 ) + 0xf ) >> 4, 256 );
        var miny = Math.max( ( Math.min( y1, y2, y3 ) + 0xf ) >> 4, 0 );
        var maxy = Math.min( ( Math.max( y1, y2, y3 ) + 0xf ) >> 4, 256 );
        // Block size, standard 8x8 (must be power of two)
        var q = 8;
        // Start in corner of 8x8 block
        minx &= ~(q - 1);
        miny &= ~(q - 1);
        // Constant part of half-edge functions
        var c1 = -dy12 * x1 - dx12 * y1;
        var c2 = -dy23 * x2 - dx23 * y2;
        var c3 = -dy31 * x3 - dx31 * y3;
        // Correct for fill convention
        if ( dy12 > 0 || ( dy12 == 0 && dx12 > 0 ) ) c1 ++;
        if ( dy23 > 0 || ( dy23 == 0 && dx23 > 0 ) ) c2 ++;
        if ( dy31 > 0 || ( dy31 == 0 && dx31 > 0 ) ) c3 ++;
        // Note this doesn't kill subpixel precision, but only because we test for >=0 (not >0).
        // It's a bit subtle. :)
        c1 = (c1 - 1) >> 4;
        c2 = (c2 - 1) >> 4;
        c3 = (c3 - 1) >> 4;
        // Set up min/max corners
        var qm1 = q - 1; // for convenience
        var nmin1 = 0, nmax1 = 0;
        var nmin2 = 0, nmax2 = 0;
        var nmin3 = 0, nmax3 = 0;
        if (dx12 >= 0) nmax1 -= qm1*dx12; else nmin1 -= qm1*dx12;
        if (dy12 >= 0) nmax1 -= qm1*dy12; else nmin1 -= qm1*dy12;
        if (dx23 >= 0) nmax2 -= qm1*dx23; else nmin2 -= qm1*dx23;
        if (dy23 >= 0) nmax2 -= qm1*dy23; else nmin2 -= qm1*dy23;
        if (dx31 >= 0) nmax3 -= qm1*dx31; else nmin3 -= qm1*dx31;
        if (dy31 >= 0) nmax3 -= qm1*dy31; else nmin3 -= qm1*dy31;
        // Loop through blocks
        var linestep = (canvasWidth-q);
        for ( var y0 = miny; y0 < maxy; y0 += q ) {
          for ( var x0 = minx; x0 < maxx; x0 += q ) {
            // Edge functions at top-left corner
            var cy1 = c1 + dx12 * y0 + dy12 * x0;
            var cy2 = c2 + dx23 * y0 + dy23 * x0;
            var cy3 = c3 + dx31 * y0 + dy31 * x0;
            // Skip block when at least one edge completely out
            if (cy1 < nmax1 || cy2 < nmax2 || cy3 < nmax3) continue;
            // Offset at top-left corner
            var offset = (x0 + y0 * canvasWidth);
            // Accept whole block when fully covered
            if (cy1 >= nmin1 && cy2 >= nmin2 && cy3 >= nmin3) {
              for ( var iy = 0; iy < q; iy ++ ) {
                for ( var ix = 0; ix < q; ix ++, offset ++ ) {
                  ram[renderTarget + offset] = color;
                }
                offset += linestep;
              }
            } else { // Partially covered block
              for ( var iy = 0; iy < q; iy ++ ) {
                var cx1 = cy1;
                var cx2 = cy2;
                var cx3 = cy3;
                for ( var ix = 0; ix < q; ix ++ ) {
                  if ( (cx1 | cx2 | cx3) >= 0 ) {
                    ram[renderTarget + offset] = color;
                  }
                  cx1 += dy12;
                  cx2 += dy23;
                  cx3 += dy31;
                  offset ++;
                }
                cy1 += dx12;
                cy2 += dx23;
                cy3 += dx31;
                offset += linestep;
              }
            }
          }
        }
      }

      function spr(sx = 0, sy = 0, sw = 16, sh = 16, x=0, y=0, flipx = false, flipy = false){


        for(var i = 0; i < sh; i++){

          for(var j = 0; j < sw; j++){

            if(y+i < 255 && x+j < 255 && y+i > -1 && x+j > -1){
              if(flipx & flipy){

                if(ram[(renderSource + ( ( sy + (sh-i) )*256+sx+(sw-j)))] > 0) {

                  ram[ (renderTarget + ((y+i)*256+x+j)) ] = pal[ ram[(renderSource + ((sy+(sh-i))*256+sx+(sw-j)))] ];

                }

              }
              else if(flipy && !flipx){

                if(ram[(renderSource + ( ( sy + (sh-i) )*256+sx+j))] > 0) {

                  ram[ (renderTarget + ((y+i)*256+x+j)) ] = ram[(renderSource + ((sy+(sh-i))*256+sx+j))];

                }

              }
              else if(flipx && !flipy){

                if(ram[(renderSource + ((sy+i)*256+sx+(sw-j)))] > 0) {

                  ram[ (renderTarget + ((y+i)*256+x+j)) ] = ram[(renderSource + ((sy+i)*256+sx+(sw-j)))];

                }

              }
              else if(!flipx && !flipy){

                if(ram[(renderSource + ((sy+i)*256+sx+j))] > 0) {

                  ram[ (renderTarget + ((y+i)*256+x+j)) ] = pal[ ram[(renderSource + ((sy+i)*256+sx+j))] ];

                }

              }
            }
          }
        }
      }

      function sspr(sx = 0, sy = 0, sw = 16, sh = 16, x=0, y=0, dw=16, dh=16, flipx = false, flipy = false){

        var xratio = sw / dw;
        var yratio = sh / dh;

        for(var i = 0; i < dh; i++){
          for(var j = 0; j < dw; j++){

            px = (j*xratio)|0;
            py = (i*yratio)|0;

            if(y+i < 255 && x+j < 255 && y+i > -1 && x+j > -1) {
              if (ram[(renderSource + ((sy + py) * 256 + sx + px))] > 0) {
                ram[(renderTarget + ((y + i) * 256 + x + j))] = ram[(renderSource + ((sy + py) * 256 + sx + px))]
              }
            }

          }
        }


      }

      function rspr( sx, sy, sw, sh, destCenterX, destCenterY, scale, angle ){

        angle = angle * 0.0174533 //convert to radians in place
        var sourceCenterX = sx + sw / 2;
        var sourceCenterY = sy + sh / 2;

       var destWidth = sw * scale;
        var destHeight = sh * scale;

       var halfWidth = (destWidth / 2 * 1.41421356237)|0 + 5;  //area will always be square, hypotenuse trick
        var halfHeight = (destHeight / 2 * 1.41421356237)|0 + 5;

       var startX = -halfWidth;
        var endX = halfWidth;

       var startY = -halfHeight;
        var endY = halfHeight;

       var scaleFactor = 1.0 / scale;

       var cos = Math.cos(-angle) * scaleFactor;
       var sin = Math.sin(-angle) * scaleFactor;

       for(let y = startY; y < endY; y++){
          for(let x = startX; x < endX; x++){

           let u = sourceCenterX + Math.round(cos * x + sin * y);
            let v = sourceCenterY + Math.round(-sin * x  + cos * y);

           let drawX = (x + destCenterX)|0;
            let drawY = (y + destCenterY)|0;

           if(u >= 0 && v >= 0 && u < sw && v < sh){
              if( ram[ (renderSource + (v * 256 + u)) ] > 0) {
                ram[(renderTarget + (drawY * 256 + drawX)) ] = ram[(renderSource + ( v * 256 + u )) ]
              }
            }

         } //end x loop

       } //end outer y loop
      }

      function checker(w, h, nRow, nCol, color) {
        //var w = 256;
        //var h = 256;
        var x = 0;
        var y = 0;

        nRow = nRow || 8;    // default number of rows
        nCol = nCol || 8;    // default number of columns

        w /= nCol;            // width of a block
        h /= nRow;            // height of a block

        for (var i = 0; i < nRow; ++i) {
          for (var j = 0, col = nCol / 2; j < col; ++j) {
            x = 2 * j * w + (i % 2 ? 0 : w);
            y = i * h;
            fr(x, y, w-1, h-1, color);
          }
        }
      }

    // util: {
    //
    //   toPolarScreen(p){
    //     let degrees = (360/256) * p.x * 0.0174533;
    //     let radius = p.y / 2;
    //     return util.polarToPoint(degrees, radius);
    //   },
    //
    //   norm(value, min, max){
    //     return (value - min) / (max - min);
    //   },
    //
    //   dist(x0, y0, x1, y1) {
    //     if(arguments.length === 2) {
    //       return this.dist(x0.x, x0.y, y0.x, y0.y);
    //     }
    //     var dx = x1 - x0,
    //     dy = y1 - y0;
    //     return Math.sqrt(dx * dx + dy * dy);
    //   },
    //
    //
    //   polarToPoint(angle, radius) {
    //     return {
    //       x: Math.cos(angle) * radius,
    //       y: Math.sin(angle) * radius
    //     };
    //   },
    //
    //   pointToPolar(p) {
    //     return {
    //       angle: Math.atan2(p.y, p.x),
    //       radius: this.magnitude(p)
    //     };
    //   },
    //
    //   magnitude(p) {
    //     return this.dist(0, 0, p.x, p.y);
    //   },
    //
    //   scale(p) {
    //
    //   }
    //
    //
    // },

    function render() {

      var i = 0x10000;  // display is first 0x10000 bytes of ram

      while (i--) {
        /*
        data is 32bit view of final screen buffer
        for each pixel on screen, we look up it's color and assign it
        */
        data[i] = colors[pal[ram[i]]];

      }

      imageData.data.set(buf8);

      ctx.putImageData(imageData, 0, 0);

    }

    playSound = function(buffer, playbackRate, pan, loop) {

      var source = audioCtx.createBufferSource();
      var gainNode = audioCtx.createGain();
      var panNode = audioCtx.createStereoPanner();

      source.buffer = buffer;
      source.connect(panNode);
      panNode.connect(gainNode);
      gainNode.connect(audioCtx.destination);

      //gainNode.connect(audioCtx.destination);
      source.playbackRate.value = playbackRate;
      source.loop = loop;
      gainNode.gain.value = 1;
      panNode.pan.value = pan;
      source.start();
      return {volume: gainNode, sound: source};
    }

function download(t,e,n){function i(t){var e=t.split(/[:;,]/),n=e[1],i="base64"==e[2]?atob:decodeURIComponent,r=i(e.pop()),o=r.length,a=0,s=new Uint8Array(o);for(a;a<o;++a)s[a]=r.charCodeAt(a);return new m([s],{type:n})}function r(t,e){if("download"in l)return l.href=t,l.setAttribute("download",w),l.innerHTML="downloading...",l.style.display="none",f.body.appendChild(l),setTimeout(function(){l.click(),f.body.removeChild(l),e===!0&&setTimeout(function(){h.URL.revokeObjectURL(l.href)},250)},66),!0;var n=f.createElement("iframe");f.body.appendChild(n),e||(t="data:"+t.replace(/^data:([\w\/\-\+]+)/,d)),n.src=t,setTimeout(function(){f.body.removeChild(n)},333)}var o,a,s,h=window,d="application/octet-stream",u=n||d,c=t,f=document,l=f.createElement("a"),p=function(t){return String(t)},m=h.Blob||h.MozBlob||h.WebKitBlob||p,g=h.MSBlobBuilder||h.WebKitBlobBuilder||h.BlobBuilder,w=e||"download";if("true"===String(this)&&(c=[c,u],u=c[0],c=c[1]),String(c).match(/^data\:[\w+\-]+\/[\w+\-]+[,;]/))return navigator.msSaveBlob?navigator.msSaveBlob(i(c),w):r(c);try{o=c instanceof m?c:new m([c],{type:u})}catch(t){g&&(a=new g,a.append([c]),o=a.getBlob(u))}if(navigator.msSaveBlob)return navigator.msSaveBlob(o,w);if(h.URL)r(h.URL.createObjectURL(o),!0);else{if("string"==typeof o||o.constructor===p)try{return r("data:"+u+";base64,"+h.btoa(o))}catch(t){return r("data:"+u+","+encodeURIComponent(o))}s=new FileReader,s.onload=function(t){r(this.result)},s.readAsDataURL(o)}return!0}window.Whammy=function(){function t(t,n){for(var i=e(t),r=3e4,o=[{id:440786851,data:[{data:1,id:17030},{data:1,id:17143},{data:4,id:17138},{data:8,id:17139},{data:"webm",id:17026},{data:2,id:17031},{data:2,id:17029}]},{id:408125543,data:[{id:357149030,data:[{data:1e6,id:2807729},{data:"whammy",id:19840},{data:"whammy",id:22337},{data:c(i.duration),id:17545}]},{id:374648427,data:[{id:174,data:[{data:1,id:215},{data:1,id:29637},{data:0,id:156},{data:"und",id:2274716},{data:"V_VP8",id:134},{data:"VP8",id:2459272},{data:1,id:131},{id:224,data:[{data:i.width,id:176},{data:i.height,id:186}]}]}]},{id:475249515,data:[]}]}],s=o[1],d=s.data[2],u=0,f=0;u<t.length;){var l={id:187,data:[{data:Math.round(f),id:179},{id:183,data:[{data:1,id:247},{data:0,size:8,id:241}]}]};d.data.push(l);var p=[],m=0;do p.push(t[u]),m+=t[u].duration,u++;while(u<t.length&&m<r);var g=0,w={id:524531317,data:[{data:Math.round(f),id:231}].concat(p.map(function(t){var e=h({discardable:0,frame:t.data.slice(4),invisible:0,keyframe:1,lacing:0,trackNum:1,timecode:Math.round(g)});return g+=t.duration,{data:e,id:163}}))};s.data.push(w),f+=m}for(var v=0,y=0;y<s.data.length;y++){y>=3&&(d.data[y-3].data[1].data[1].data=v);var b=a([s.data[y]],n);v+=b.size||b.byteLength||b.length,2!=y&&(s.data[y]=b)}return a(o,n)}function e(t){for(var e=t[0].width,n=t[0].height,i=t[0].duration,r=1;r<t.length;r++){if(t[r].width!=e)throw"Frame "+(r+1)+" has a different width";if(t[r].height!=n)throw"Frame "+(r+1)+" has a different height";if(t[r].duration<0||t[r].duration>32767)throw"Frame "+(r+1)+" has a weird duration (must be between 0 and 32767)";i+=t[r].duration}return{duration:i,width:e,height:n}}function n(t){for(var e=[];t>0;)e.push(255&t),t>>=8;return new Uint8Array(e.reverse())}function i(t,e){for(var n=new Uint8Array(e),i=e-1;i>=0;i--)n[i]=255&t,t>>=8;return n}function r(t){for(var e=new Uint8Array(t.length),n=0;n<t.length;n++)e[n]=t.charCodeAt(n);return e}function o(t){var e=[],n=t.length%8?new Array(9-t.length%8).join("0"):"";t=n+t;for(var i=0;i<t.length;i+=8)e.push(parseInt(t.substr(i,8),2));return new Uint8Array(e)}function a(t,e){for(var h=[],d=0;d<t.length;d++)if("id"in t[d]){var u=t[d].data;if("object"==typeof u&&(u=a(u,e)),"number"==typeof u&&(u="size"in t[d]?i(u,t[d].size):o(u.toString(2))),"string"==typeof u&&(u=r(u)),u.length);for(var c=u.size||u.byteLength||u.length,f=0,l=56;l>0;l-=7)if(c>Math.pow(2,l)-2){f=l/7;break}var p=c.toString(2),m=new Array(8*(f+1)+1).join("0"),g=new Array(f+1).join("0")+1,w=m.substr(0,m.length-p.length-g.length)+p,v=g+w;h.push(n(t[d].id)),h.push(o(v)),h.push(u)}else h.push(t[d]);if(e){var y=s(h);return new Uint8Array(y)}return new Blob(h,{type:"video/webm"})}function s(t,e){null==e&&(e=[]);for(var n=0;n<t.length;n++)"object"==typeof t[n]?s(t[n],e):e.push(t[n]);return e}function h(t){var e=0;if(t.keyframe&&(e|=128),t.invisible&&(e|=8),t.lacing&&(e|=t.lacing<<1),t.discardable&&(e|=1),t.trackNum>127)throw"TrackNumber > 127 not supported";var n=[128|t.trackNum,t.timecode>>8,255&t.timecode,e].map(function(t){return String.fromCharCode(t)}).join("")+t.frame;return n}function d(t){for(var e=t.RIFF[0].WEBP[0],n=e.indexOf("*"),i=0,r=[];i<4;i++)r[i]=e.charCodeAt(n+3+i);var o,a,s,h,d;return d=r[1]<<8|r[0],o=16383&d,a=d>>14,d=r[3]<<8|r[2],s=16383&d,h=d>>14,{width:o,height:s,data:e,riff:t}}function u(t){for(var e=0,n={};e<t.length;){var i=t.substr(e,4);if(n[i]=n[i]||[],"RIFF"==i||"LIST"==i){var r=parseInt(t.substr(e+4,4).split("").map(function(t){var e=t.charCodeAt(0).toString(2);return new Array(8-e.length+1).join("0")+e}).join(""),2),o=t.substr(e+4+4,r);e+=8+r,n[i].push(u(o))}else"WEBP"==i?(n[i].push(t.substr(e+8)),e=t.length):(n[i].push(t.substr(e+4)),e=t.length)}return n}function c(t){return[].slice.call(new Uint8Array(new Float64Array([t]).buffer),0).map(function(t){return String.fromCharCode(t)}).reverse().join("")}function f(t,e){this.frames=[],this.duration=1e3/t,this.quality=e||.8}return f.prototype.add=function(t,e){if("undefined"!=typeof e&&this.duration)throw"you can't pass a duration if the fps is set";if("undefined"==typeof e&&!this.duration)throw"if you don't have the fps set, you need to have durations here.";if(t.canvas&&(t=t.canvas),t.toDataURL)t=t.getContext("2d").getImageData(0,0,t.width,t.height);else if("string"!=typeof t)throw"frame must be a a HTMLCanvasElement, a CanvasRenderingContext2D or a DataURI formatted string";if("string"==typeof t&&!/^data:image\/webp;base64,/gi.test(t))throw"Input must be formatted properly as a base64 encoded DataURI of type image/webp";this.frames.push({image:t,duration:e||this.duration})},f.prototype.encodeFrames=function(t){if(this.frames[0].image instanceof ImageData){var e=this.frames,n=document.createElement("canvas"),i=n.getContext("2d");n.width=this.frames[0].image.width,n.height=this.frames[0].image.height;var r=function(o){var a=e[o];i.putImageData(a.image,0,0),a.image=n.toDataURL("image/webp",this.quality),o<e.length-1?setTimeout(function(){r(o+1)},1):t()}.bind(this);r(0)}else t()},f.prototype.compile=function(e,n){this.encodeFrames(function(){var i=new t(this.frames.map(function(t){var e=d(u(atob(t.image.slice(23))));return e.duration=t.duration,e}),e);n(i)}.bind(this))},{Video:f,fromImageArray:function(e,n,i){return t(e.map(function(t){var e=d(u(atob(t.slice(23))));return e.duration=1e3/n,e}),i)},toWebM:t}}(),function(){"use strict";function t(t){var e,n=new Uint8Array(t);for(e=0;e<t;e+=1)n[e]=0;return n}function e(e,n,i,r){var o=n+i,a=t((parseInt(o/r)+1)*r);return a.set(e),a}function n(t,e,n){return t=t.toString(n||8),"000000000000".substr(t.length+12-e)+t}function i(e,n,i){var r,o;for(n=n||t(e.length),i=i||0,r=0,o=e.length;r<o;r+=1)n[i]=e.charCodeAt(r),i+=1;return n}function r(t){function e(t){return o[t>>18&63]+o[t>>12&63]+o[t>>6&63]+o[63&t]}var n,i,r,a=t.length%3,s="";for(n=0,r=t.length-a;n<r;n+=3)i=(t[n]<<16)+(t[n+1]<<8)+t[n+2],s+=e(i);switch(s.length%4){case 1:s+="=";break;case 2:s+="=="}return s}var o=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"];window.utils={},window.utils.clean=t,window.utils.pad=n,window.utils.extend=e,window.utils.stringToUint8=i,window.utils.uint8ToBase64=r}(),function(){"use strict";function t(t,i){var r=n.clean(512),o=0;return e.forEach(function(e){var n,i,a=t[e.field]||"";for(n=0,i=a.length;n<i;n+=1)r[o]=a.charCodeAt(n),o+=1;o+=e.length-n}),"function"==typeof i?i(r,o):r}var e,n=window.utils;e=[{field:"fileName",length:100},{field:"fileMode",length:8},{field:"uid",length:8},{field:"gid",length:8},{field:"fileSize",length:12},{field:"mtime",length:12},{field:"checksum",length:8},{field:"type",length:1},{field:"linkName",length:100},{field:"ustar",length:8},{field:"owner",length:32},{field:"group",length:32},{field:"majorNumber",length:8},{field:"minorNumber",length:8},{field:"filenamePrefix",length:155},{field:"padding",length:12}],window.header={},window.header.structure=e,window.header.format=t}(),function(){"use strict";function t(t){this.written=0,e=(t||20)*r,this.out=i.clean(e),this.blocks=[],this.length=0}var e,n=window.header,i=window.utils,r=512;t.prototype.append=function(t,e,o,a){var s,h,d,u,c,f,l;if("string"==typeof e)e=i.stringToUint8(e);else if(e.constructor!==Uint8Array.prototype.constructor)throw"Invalid input type. You gave me: "+e.constructor.toString().match(/function\s*([$A-Za-z_][0-9A-Za-z_]*)\s*\(/)[1];"function"==typeof o&&(a=o,o={}),o=o||{},d=o.mode||4095&parseInt("777",8),u=o.mtime||Math.floor(+new Date/1e3),c=o.uid||0,f=o.gid||0,s={fileName:t,fileMode:i.pad(d,7),uid:i.pad(c,7),gid:i.pad(f,7),fileSize:i.pad(e.length,11),mtime:i.pad(u,11),checksum:"        ",type:"0",ustar:"ustar  ",owner:o.owner||"",group:o.group||""},h=0,Object.keys(s).forEach(function(t){var e,n,i=s[t];for(e=0,n=i.length;e<n;e+=1)h+=i.charCodeAt(e)}),s.checksum=i.pad(h,6)+"\0 ",l=n.format(s);var p=Math.ceil(l.length/r)*r,m=Math.ceil(e.length/r)*r;this.blocks.push({header:l,input:e,headerLength:p,inputLength:m})},t.prototype.save=function(){var t=[],e=[],n=0,i=Math.pow(2,20),o=[];return this.blocks.forEach(function(t){n+t.headerLength+t.inputLength>i&&(e.push({blocks:o,length:n}),o=[],n=0),o.push(t),n+=t.headerLength+t.inputLength}),e.push({blocks:o,length:n}),e.forEach(function(e){var n=new Uint8Array(e.length),i=0;e.blocks.forEach(function(t){n.set(t.header,i),i+=t.headerLength,n.set(t.input,i),i+=t.inputLength}),t.push(n)}),t.push(new Uint8Array(2*r)),new Blob(t,{type:"octet/stream"})},t.prototype.clear=function(){this.written=0,this.out=i.clean(e)},window.Tar=t}(),function(t){function e(t,n){if({}.hasOwnProperty.call(e.cache,t))return e.cache[t];var i=e.resolve(t);if(!i)throw new Error("Failed to resolve module "+t);var r={id:t,require:e,filename:t,exports:{},loaded:!1,parent:n,children:[]};n&&n.children.push(r);var o=t.slice(0,t.lastIndexOf("/")+1);return e.cache[t]=r.exports,i.call(r.exports,r,r.exports,o,t),r.loaded=!0,e.cache[t]=r.exports}e.modules={},e.cache={},e.resolve=function(t){return{}.hasOwnProperty.call(e.modules,t)?e.modules[t]:void 0},e.define=function(t,n){e.modules[t]=n};var n=function(e){return e="/",{title:"browser",version:"v0.10.26",browser:!0,env:{},argv:[],nextTick:t.setImmediate||function(t){setTimeout(t,0)},cwd:function(){return e},chdir:function(t){e=t}}}();e.define("/gif.coffee",function(t,n,i,r){function o(t,e){return{}.hasOwnProperty.call(t,e)}function a(t,e){for(var n=0,i=e.length;n<i;++n)if(n in e&&e[n]===t)return!0;return!1}function s(t,e){function n(){this.constructor=t}for(var i in e)o(e,i)&&(t[i]=e[i]);return n.prototype=e.prototype,t.prototype=new n,t.__super__=e.prototype,t}var h,d,u,c,f;u=e("events",t).EventEmitter,h=e("/browser.coffee",t),f=function(t){function e(t){var e,n;this.running=!1,this.options={},this.frames=[],this.freeWorkers=[],this.activeWorkers=[],this.setOptions(t);for(e in d)n=d[e],null!=this.options[e]?this.options[e]:this.options[e]=n}return s(e,t),d={workerScript:"gif.worker.js",workers:2,repeat:0,background:"#fff",quality:10,width:null,height:null,transparent:null},c={delay:500,copy:!1},e.prototype.setOption=function(t,e){return this.options[t]=e,null==this._canvas||"width"!==t&&"height"!==t?void 0:this._canvas[t]=e},e.prototype.setOptions=function(t){var e,n;return function(i){for(e in t)o(t,e)&&(n=t[e],i.push(this.setOption(e,n)));return i}.call(this,[])},e.prototype.addFrame=function(t,e){var n,i;null==e&&(e={}),n={},n.transparent=this.options.transparent;for(i in c)n[i]=e[i]||c[i];if(null!=this.options.width||this.setOption("width",t.width),null!=this.options.height||this.setOption("height",t.height),"undefined"!=typeof ImageData&&null!=ImageData&&t instanceof ImageData)n.data=t.data;else if("undefined"!=typeof CanvasRenderingContext2D&&null!=CanvasRenderingContext2D&&t instanceof CanvasRenderingContext2D||"undefined"!=typeof WebGLRenderingContext&&null!=WebGLRenderingContext&&t instanceof WebGLRenderingContext)e.copy?n.data=this.getContextData(t):n.context=t;else{if(null==t.childNodes)throw new Error("Invalid image");e.copy?n.data=this.getImageData(t):n.image=t}return this.frames.push(n)},e.prototype.render=function(){var t,e;if(this.running)throw new Error("Already running");if(null==this.options.width||null==this.options.height)throw new Error("Width and height must be set prior to rendering");this.running=!0,this.nextFrame=0,this.finishedFrames=0,this.imageParts=function(e){for(var n=function(){var t;t=[];for(var e=0;0<=this.frames.length?e<this.frames.length:e>this.frames.length;0<=this.frames.length?++e:--e)t.push(e);return t}.apply(this,arguments),i=0,r=n.length;i<r;++i)t=n[i],e.push(null);return e}.call(this,[]),e=this.spawnWorkers();for(var n=function(){var t;t=[];for(var n=0;0<=e?n<e:n>e;0<=e?++n:--n)t.push(n);return t}.apply(this,arguments),i=0,r=n.length;i<r;++i)t=n[i],this.renderNextFrame();return this.emit("start"),this.emit("progress",0)},e.prototype.abort=function(){for(var t;;){if(t=this.activeWorkers.shift(),!(null!=t))break;console.log("killing active worker"),t.terminate()}return this.running=!1,this.emit("abort")},e.prototype.spawnWorkers=function(){var t;return t=Math.min(this.options.workers,this.frames.length),function(){var e;e=[];for(var n=this.freeWorkers.length;this.freeWorkers.length<=t?n<t:n>t;this.freeWorkers.length<=t?++n:--n)e.push(n);return e}.apply(this,arguments).forEach(function(t){return function(e){var n;return console.log("spawning worker "+e),n=new Worker(t.options.workerScript),n.onmessage=function(t){return function(e){return t.activeWorkers.splice(t.activeWorkers.indexOf(n),1),t.freeWorkers.push(n),t.frameFinished(e.data)}}(t),t.freeWorkers.push(n)}}(this)),t},e.prototype.frameFinished=function(t){return console.log("frame "+t.index+" finished - "+this.activeWorkers.length+" active"),this.finishedFrames++,this.emit("progress",this.finishedFrames/this.frames.length),this.imageParts[t.index]=t,a(null,this.imageParts)?this.renderNextFrame():this.finishRendering()},e.prototype.finishRendering=function(){var t,e,n,i,r,o,a;r=0;for(var s=0,h=this.imageParts.length;s<h;++s)e=this.imageParts[s],r+=(e.data.length-1)*e.pageSize+e.cursor;r+=e.pageSize-e.cursor,console.log("rendering finished - filesize "+Math.round(r/1e3)+"kb"),t=new Uint8Array(r),o=0;for(var d=0,u=this.imageParts.length;d<u;++d){e=this.imageParts[d];for(var c=0,f=e.data.length;c<f;++c)a=e.data[c],n=c,t.set(a,o),o+=n===e.data.length-1?e.cursor:e.pageSize}return i=new Blob([t],{type:"image/gif"}),this.emit("finished",i,t)},e.prototype.renderNextFrame=function(){var t,e,n;if(0===this.freeWorkers.length)throw new Error("No free workers");return this.nextFrame>=this.frames.length?void 0:(t=this.frames[this.nextFrame++],n=this.freeWorkers.shift(),e=this.getTask(t),console.log("starting frame "+(e.index+1)+" of "+this.frames.length),this.activeWorkers.push(n),n.postMessage(e))},e.prototype.getContextData=function(t){return t.getImageData(0,0,this.options.width,this.options.height).data},e.prototype.getImageData=function(t){var e;return null!=this._canvas||(this._canvas=document.createElement("canvas"),this._canvas.width=this.options.width,this._canvas.height=this.options.height),e=this._canvas.getContext("2d"),e.setFill=this.options.background,e.fr(0,0,this.options.width,this.options.height),e.drawImage(t,0,0),this.getContextData(e)},e.prototype.getTask=function(t){var e,n;if(e=this.frames.indexOf(t),n={index:e,last:e===this.frames.length-1,delay:t.delay,transparent:t.transparent,width:this.options.width,height:this.options.height,quality:this.options.quality,repeat:this.options.repeat,canTransfer:"chrome"===h.name},null!=t.data)n.data=t.data;else if(null!=t.context)n.data=this.getContextData(t.context);else{if(null==t.image)throw new Error("Invalid frame");n.data=this.getImageData(t.image)}return n},e}(u),t.exports=f}),e.define("/browser.coffee",function(t,e,n,i){var r,o,a,s,h;s=navigator.userAgent.toLowerCase(),a=navigator.platform.toLowerCase(),h=s.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/)||[null,"unknown",0],o="ie"===h[1]&&document.documentMode,r={name:"version"===h[1]?h[3]:h[1],version:o||parseFloat("opera"===h[1]&&h[4]?h[4]:h[2]),platform:{name:s.match(/ip(?:ad|od|hone)/)?"ios":(s.match(/(?:webos|android)/)||a.match(/mac|win|linux/)||["other"])[0]}},r[r.name]=!0,r[r.name+parseInt(r.version,10)]=!0,r.platform[r.platform.name]=!0,t.exports=r}),e.define("events",function(t,e,i,r){n.EventEmitter||(n.EventEmitter=function(){});var o=e.EventEmitter=n.EventEmitter,a="function"==typeof Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},s=10;o.prototype.setMaxListeners=function(t){this._events||(this._events={}),this._events.maxListeners=t},o.prototype.emit=function(t){if("error"===t&&(!this._events||!this._events.error||a(this._events.error)&&!this._events.error.length))throw arguments[1]instanceof Error?arguments[1]:new Error("Uncaught, unspecified 'error' event.");if(!this._events)return!1;var e=this._events[t];if(!e)return!1;if("function"!=typeof e){if(a(e)){for(var n=Array.prototype.slice.call(arguments,1),i=e.slice(),r=0,o=i.length;r<o;r++)i[r].apply(this,n);return!0}return!1}switch(arguments.length){case 1:e.call(this);break;case 2:e.call(this,arguments[1]);break;case 3:e.call(this,arguments[1],arguments[2]);break;default:var n=Array.prototype.slice.call(arguments,1);e.apply(this,n)}return!0},o.prototype.addListener=function(t,e){if("function"!=typeof e)throw new Error("addListener only takes instances of Function");if(this._events||(this._events={}),this.emit("newListener",t,e),this._events[t])if(a(this._events[t])){if(!this._events[t].warned){var n;n=void 0!==this._events.maxListeners?this._events.maxListeners:s,n&&n>0&&this._events[t].length>n&&(this._events[t].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[t].length),console.trace())}this._events[t].push(e)}else this._events[t]=[this._events[t],e];else this._events[t]=e;return this},o.prototype.on=o.prototype.addListener,o.prototype.once=function(t,e){var n=this;return n.on(t,function i(){n.removeListener(t,i),e.apply(this,arguments)}),this},o.prototype.removeListener=function(t,e){if("function"!=typeof e)throw new Error("removeListener only takes instances of Function");if(!this._events||!this._events[t])return this;var n=this._events[t];if(a(n)){var i=n.indexOf(e);if(i<0)return this;n.splice(i,1),0==n.length&&delete this._events[t]}else this._events[t]===e&&delete this._events[t];return this},o.prototype.removeAllListeners=function(t){return t&&this._events&&this._events[t]&&(this._events[t]=null),this},o.prototype.listeners=function(t){return this._events||(this._events={}),this._events[t]||(this._events[t]=[]),a(this._events[t])||(this._events[t]=[this._events[t]]),this._events[t]}}),t.GIF=e("/gif.coffee")}.call(this,this),function(){"use strict";function t(t){return t&&t.Object===Object?t:null}function e(t){return String("0000000"+t).slice(-7)}function n(){function t(){return Math.floor(65536*(1+Math.random())).toString(16).substring(1)}return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()}function i(t){var e={};this.settings=t,this.on=function(t,n){e[t]=n},this.emit=function(t){var n=e[t];n&&n.apply(null,Array.prototype.slice.call(arguments,1))},this.filename=t.name||n(),this.extension="",this.mimeType=""}function r(t){i.call(this,t),this.extension=".tar",this.mimeType="application/x-tar",this.fileExtension="",this.tape=null,this.count=0}function o(t){r.call(this,t),this.type="image/png",this.fileExtension=".png"}function a(t){r.call(this,t),this.type="image/jpeg",this.fileExtension=".jpg",this.quality=t.quality/100||.8}function s(t){var e=document.createElement("canvas");"image/webp"!==e.toDataURL("image/webp").substr(5,10)&&console.log("WebP not supported - try another export format"),i.call(this,t),t.quality=t.quality/100||.8,this.extension=".webm",this.mimeType="video/webm",this.baseFilename=this.filename,this.frames=[],this.part=1}function h(t){i.call(this,t),t.quality=t.quality/100||.8,this.encoder=new FFMpegServer.Video(t),this.encoder.on("process",function(){this.emit("process")}.bind(this)),this.encoder.on("finished",function(t,e){var n=this.callback;n&&(this.callback=void 0,n(t,e))}.bind(this)),this.encoder.on("progress",function(t){this.settings.onProgress&&this.settings.onProgress(t)}.bind(this)),this.encoder.on("error",function(t){alert(JSON.stringify(t,null,2))}.bind(this))}function d(t){i.call(this,t),this.framerate=this.settings.framerate,this.type="video/webm",this.extension=".webm",this.stream=null,this.mediaRecorder=null,this.chunks=[]}function u(t){i.call(this,t),t.quality=31-(30*t.quality/100||10),t.workers=t.workers||4,this.extension=".gif",this.mimeType="image/gif",this.canvas=document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.sizeSet=!1,this.encoder=new GIF({workers:t.workers,quality:t.quality,workerScript:t.workersPath+"gif.worker.js"}),this.encoder.on("progress",function(t){this.settings.onProgress&&this.settings.onProgress(t)}.bind(this)),this.encoder.on("finished",function(t){var e=this.callback;e&&(this.callback=void 0,e(t))}.bind(this))}function c(t){function e(){function t(){return this._hooked||(this._hooked=!0,this._hookedTime=this.currentTime||0,this.pause(),et.push(this)),this._hookedTime+S.startTime}b("Capturer start"),A=window.Date.now(),L=A+S.startTime,D=window.performance.now(),E=D+S.startTime,window.Date.prototype.getTime=function(){return L},window.Date.now=function(){return L},window.setTimeout=function(t,e){var n={callback:t,time:e,triggerTime:L+e};return B.push(n),b("Timeout set to "+n.time),n},window.clearTimeout=function(t){for(var e=0;e<B.length;e++)B[e]!=t||(B.splice(e,1),b("Timeout cleared"))},window.setInterval=function(t,e){var n={callback:t,time:e,triggerTime:L+e};return j.push(n),b("Interval set to "+n.time),n},window.clearInterval=function(t){return b("clear Interval"),null},window.requestAnimationFrame=function(t){U.push(t)},window.performance.now=function(){return E};try{Object.defineProperty(HTMLVideoElement.prototype,"currentTime",{get:t}),Object.defineProperty(HTMLAudioElement.prototype,"currentTime",{get:t})}catch(t){b(t)}}function n(){e(),I.start(),M=!0}function i(){M=!1,I.stop(),f()}function r(t,e){Z(t,0,e)}function c(){r(v)}function f(){b("Capturer stop"),window.setTimeout=Z,window.setInterval=J,window.clearTimeout=Y,window.requestAnimationFrame=$,window.Date.prototype.getTime=tt,window.Date.now=Q,window.performance.now=X}function l(){var t=R/S.framerate;(S.frameLimit&&R>=S.frameLimit||S.timeLimit&&t>=S.timeLimit)&&(i(),y());var e=new Date(null);e.setSeconds(t),S.motionBlurFrames>2?P.textContent="CCapture "+S.format+" | "+R+" frames ("+O+" inter) | "+e.toISOString().substr(11,8):P.textContent="CCapture "+S.format+" | "+R+" frames | "+e.toISOString().substr(11,8)}function p(t){N.width===t.width&&N.height===t.height||(N.width=t.width,N.height=t.height,q=new Uint16Array(N.height*N.width*4),V.fillStyle="#0",V.fr(0,0,N.width,N.height))}function m(t){V.drawImage(t,0,0),z=V.getImageData(0,0,N.width,N.height);for(var e=0;e<q.length;e+=4)q[e]+=z.data[e],q[e+1]+=z.data[e+1],q[e+2]+=z.data[e+2];O++}function g(){for(var t=z.data,e=0;e<q.length;e+=4)t[e]=2*q[e]/S.motionBlurFrames,t[e+1]=2*q[e+1]/S.motionBlurFrames,t[e+2]=2*q[e+2]/S.motionBlurFrames;V.putImageData(z,0,0),I.add(N),R++,O=0,b("Full MB Frame! "+R+" "+L);for(var e=0;e<q.length;e+=4)q[e]=0,q[e+1]=0,q[e+2]=0;gc()}function w(t){M&&(S.motionBlurFrames>2?(p(t),m(t),O>=.5*S.motionBlurFrames?g():c()):(I.add(t),R++,b("Full Frame! "+R)))}function v(){var t=1e3/S.framerate,e=(R+O/S.motionBlurFrames)*t;L=A+e,E=D+e,et.forEach(function(t){t._hookedTime=e/1e3}),l(),b("Frame: "+R+" "+O);for(var n=0;n<B.length;n++)L>=B[n].triggerTime&&(r(B[n].callback),B.splice(n,1));for(var n=0;n<j.length;n++)L>=j[n].triggerTime&&(r(j[n].callback),j[n].triggerTime+=j[n].time);U.forEach(function(t){r(t,L-k)}),U=[]}function y(t){t||(t=function(t){return download(t,I.filename+I.extension,I.mimeType),!1}),I.save(t)}function b(t){_&&console.log(t)}function x(t,e){W[t]=e}function T(t){var e=W[t];e&&e.apply(null,Array.prototype.slice.call(arguments,1))}function C(t){T("progress",t)}var _,F,L,A,E,D,c,I,S=t||{},B=(new Date,[]),j=[],R=0,O=0,U=[],M=!1,W={};S.framerate=S.framerate||60,S.motionBlurFrames=2*(S.motionBlurFrames||1),_=S.verbose||!1,F=S.display||!1,S.step=1e3/S.framerate,S.timeLimit=S.timeLimit||0,S.frameLimit=S.frameLimit||0,S.startTime=S.startTime||0;var P=document.createElement("div");P.style.position="absolute",P.style.left=P.style.top=0,P.style.backgroundColor="black",P.style.fontFamily="monospace",P.style.fontSize="11px",P.style.padding="5px",P.style.color="red",P.style.zIndex=1e5,S.display&&document.body.appendChild(P);var q,z,N=document.createElement("canvas"),V=N.getContext("2d");b("Step is set to "+S.step+"ms");var H={gif:u,webm:s,ffmpegserver:h,png:o,jpg:a,"webm-mediarecorder":d},G=H[S.format];if(!G)throw"Error: Incorrect or missing format: Valid formats are "+Object.keys(H).join(", ");if(I=new G(S),I.step=c,I.on("process",v),I.on("progress",C),"performance"in window==0&&(window.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in window.performance==0){var K=Date.now();performance.timing&&performance.timing.navigationStart&&(K=performance.timing.navigationStart),window.performance.now=function(){return Date.now()-K}}var Z=window.setTimeout,J=window.setInterval,Y=window.clearTimeout,$=window.requestAnimationFrame,Q=window.Date.now,X=window.performance.now,tt=window.Date.prototype.getTime,et=[];return{start:n,capture:w,stop:i,save:y,on:x}}var f={function:!0,object:!0},l=(parseFloat,parseInt,f[typeof exports]&&exports&&!exports.nodeType?exports:void 0),p=f[typeof module]&&module&&!module.nodeType?module:void 0,m=p&&p.exports===l?l:void 0,g=t(l&&p&&"object"==typeof global&&global),w=t(f[typeof self]&&self),v=t(f[typeof window]&&window),y=t(f[typeof this]&&this),b=g||v!==(y&&y.window)&&v||w||y||Function("return this")();"gc"in window||(window.gc=function(){}),HTMLCanvasElement.prototype.toBlob||Object.defineProperty(HTMLCanvasElement.prototype,"toBlob",{value:function(t,e,n){for(var i=atob(this.toDataURL(e,n).split(",")[1]),r=i.length,o=new Uint8Array(r),a=0;a<r;a++)o[a]=i.charCodeAt(a);t(new Blob([o],{type:e||"image/png"}))}}),function(){if("performance"in window==0&&(window.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in window.performance==0){var t=Date.now();performance.timing&&performance.timing.navigationStart&&(t=performance.timing.navigationStart),window.performance.now=function(){return Date.now()-t}}}();var k=window.Date.now();i.prototype.start=function(){},i.prototype.stop=function(){},i.prototype.add=function(){},i.prototype.save=function(){},i.prototype.dispose=function(){},i.prototype.safeToProceed=function(){return!0},i.prototype.step=function(){console.log("Step not set!")},r.prototype=Object.create(i.prototype),r.prototype.start=function(){this.dispose()},r.prototype.add=function(t){var n=new FileReader;n.onload=function(){this.tape.append(e(this.count)+this.fileExtension,new Uint8Array(n.result)),this.count++,this.step()}.bind(this),n.readAsArrayBuffer(t)},r.prototype.save=function(t){t(this.tape.save())},r.prototype.dispose=function(){this.tape=new Tar,this.count=0},o.prototype=Object.create(r.prototype),o.prototype.add=function(t){t.toBlob(function(t){r.prototype.add.call(this,t)}.bind(this),this.type)},a.prototype=Object.create(r.prototype),a.prototype.add=function(t){t.toBlob(function(t){r.prototype.add.call(this,t)}.bind(this),this.type,this.quality)},s.prototype=Object.create(i.prototype),s.prototype.start=function(t){this.dispose()},s.prototype.add=function(t){this.frames.push(t.toDataURL("image/webp",this.quality)),this.settings.autoSaveTime>0&&this.frames.length/this.settings.framerate>=this.settings.autoSaveTime?this.save(function(t){this.filename=this.baseFilename+"-part-"+e(this.part),download(t,this.filename+this.extension,this.mimeType),this.dispose(),this.part++,this.filename=this.baseFilename+"-part-"+e(this.part),this.step()}.bind(this)):this.step()},s.prototype.save=function(t){if(this.frames.length){var e=Whammy.fromImageArray(this.frames,this.settings.framerate),n=new Blob([e],{type:"octet/stream"});t(n)}},s.prototype.dispose=function(t){this.frames=[]},h.prototype=Object.create(i.prototype),h.prototype.start=function(){this.encoder.start(this.settings)},h.prototype.add=function(t){this.encoder.add(t)},h.prototype.save=function(t){this.callback=t,this.encoder.end()},h.prototype.safeToProceed=function(){return this.encoder.safeToProceed()},d.prototype=Object.create(i.prototype),d.prototype.add=function(t){this.stream||(this.stream=t.captureStream(this.framerate),this.mediaRecorder=new MediaRecorder(this.stream),this.mediaRecorder.start(),this.mediaRecorder.ondataavailable=function(t){this.chunks.push(t.data)}.bind(this)),this.step()},d.prototype.save=function(t){this.mediaRecorder.onstop=function(e){var n=new Blob(this.chunks,{type:"video/webm"});this.chunks=[],t(n)}.bind(this),this.mediaRecorder.stop()},u.prototype=Object.create(i.prototype),u.prototype.add=function(t){this.sizeSet||(this.encoder.setOption("width",t.width),this.encoder.setOption("height",t.height),this.sizeSet=!0),this.canvas.width=t.width,this.canvas.height=t.height,this.ctx.drawImage(t,0,0),this.encoder.addFrame(this.ctx,{copy:!0,delay:this.settings.step}),this.step()},u.prototype.save=function(t){this.callback=t,this.encoder.render()},(v||w||{}).CCapture=c,"function"==typeof define&&"object"==typeof define.amd&&define.amd?define(function(){return c}):l&&p?(m&&((p.exports=c).CCapture=c),l.CCapture=c):b.CCapture=c}();
function Particle() {

  this.inUse = false;

  this.init = function(){
    this.x = -500;
    this.y = -500;
    this.dead = true;
    this.xvel = 0;
    this.yvel = 1;
    this.life = 1;
  }

  Particle.prototype.spawn = function(opt) {
    this.x = opt.x;
    this.y = opt.y;
    this.xvel = opt.xvel;
    this.yvel = opt.yvel;
    this.inUse = true;
    this.life = opt.life || 1;
    this.remaining = opt.life || 1;
    this.radius = opt.radius || 1;
    this.color = opt.color || 21;
    this.dead = false;
  }

  Particle.prototype.use = function(dt){
    if(this.dead) {
      return true;
    }
    else {
      this.remaining -= dt;
      this.x += dt * this.xvel;
      this.y += dt * this.yvel;
      this.draw();
      //console.log('bullet used/updated');
        if(this.remaining <= 0) {
          this.dead = true;
          return true;
        }
        if(this.y < 0){
          this.dead = true;
        }
    }
    return false;
  }


  Particle.prototype.clear = function(){
    this.x = -500;
    this.y = -500;
    this.dead = true;
    this.xvel = 0;
    this.yvel = 0;
    this.life = 1;
    this.inUse = false;
  }

  Particle.prototype.draw = function(){
    circle(this.x, this.y, 0|Math.random()*4, 21);
  }


}

/**
 * Created by ryan on 9/4/16.
 */
/**
 * The Object Pool. Unused objects are grabbed from the back of
 * the array and pushed to the front of the array. When using an
 * object, if the object is ready to be removed, it splices the
 * array and pushes the object to the back to be reused.
 */
function Pool(poolSize, objClass) {
    var size = poolSize; // Max objects allowed in the pool
    var pool = [];
    /*
     * Populates the pool array with objects
     */
    this.init = function() {
        for (var i = 0; i < size; i++) {
            // Initialize the objects
            var obj = new objClass();
            obj.init();
            pool[i] = obj;
        }
    };
    /*
     * Grabs the last item in the list and initializes it and
     * pushes it to the front of the array.
     */
    this.get = function(opt) {
        // If the last item in the array is in use, the pool is full
        if(!pool[size - 1].inUse) {
            pool[size - 1].spawn(opt);
            pool.unshift(pool.pop());
            return pool[size -1];
        }
    };

    this.getPool = function() {
        return pool;
    }
    /*
     * Uses any alive objects in the pool. If the call returns true,
     * the object is ready to be cleared and reused.
     */
    this.use = function() {
        for (var i = 0; i < size; i++) {
            //.log('pool use iteration');
            // Only use objects that are currently in use
            if (pool[i].inUse) {
                if (pool[i].use(dt)) {
                    pool[i].clear();
                    pool.push((pool.splice(i,1))[0]);
                }
            } else {
                // The first occurrence of an unused item we can
                // break looping over the objects.
                break;
            }
        }
    };
};

/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil; -*-
*
* Copyright (c) 2011-2013 Marcus Geelnard
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
*    claim that you wrote the original software. If you use this software
*    in a product, an acknowledgment in the product documentation would be
*    appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
*    misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
*    distribution.
*
*/

"use strict";

var CPlayer = function() {

    //--------------------------------------------------------------------------
    // Private methods
    //--------------------------------------------------------------------------

    // Oscillators
    var osc_sin = function (value) {
        return Math.sin(value * 6.283184);
    };

    var osc_saw = function (value) {
        return 2 * (value % 1) - 1;
    };

    var osc_square = function (value) {
        return (value % 1) < 0.5 ? 1 : -1;
    };

    var osc_tri = function (value) {
        var v2 = (value % 1) * 4;
        if(v2 < 2) return v2 - 1;
        return 3 - v2;
    };

    var getnotefreq = function (n) {
        // 174.61.. / 44100 = 0.003959503758 (F3)
        return 0.003959503758 * Math.pow(2, (n - 128) / 12);
    };

    var createNote = function (instr, n, rowLen) {
        var osc1 = mOscillators[instr.i[0]],
            o1vol = instr.i[1],
            o1xenv = instr.i[3],
            osc2 = mOscillators[instr.i[4]],
            o2vol = instr.i[5],
            o2xenv = instr.i[8],
            noiseVol = instr.i[9],
            attack = instr.i[10] * instr.i[10] * 4,
            sustain = instr.i[11] * instr.i[11] * 4,
            release = instr.i[12] * instr.i[12] * 4,
            releaseInv = 1 / release,
            arp = instr.i[13],
            arpInterval = rowLen * Math.pow(2, 2 - instr.i[14]);

        var noteBuf = new Int32Array(attack + sustain + release);

        // Re-trig oscillators
        var c1 = 0, c2 = 0;

        // Local variables.
        var j, j2, e, t, rsample, o1t, o2t;

        // Generate one note (attack + sustain + release)
        for (j = 0, j2 = 0; j < attack + sustain + release; j++, j2++) {
            if (j2 >= 0) {
                // Switch arpeggio note.
                arp = (arp >> 8) | ((arp & 255) << 4);
                j2 -= arpInterval;

                // Calculate note frequencies for the oscillators
                o1t = getnotefreq(n + (arp & 15) + instr.i[2] - 128);
                o2t = getnotefreq(n + (arp & 15) + instr.i[6] - 128) * (1 + 0.0008 * instr.i[7]);
            }

            // Envelope
            e = 1;
            if (j < attack) {
                e = j / attack;
            } else if (j >= attack + sustain) {
                e -= (j - attack - sustain) * releaseInv;
            }

            // Oscillator 1
            t = o1t;
            if (o1xenv) {
                t *= e * e;
            }
            c1 += t;
            rsample = osc1(c1) * o1vol;

            // Oscillator 2
            t = o2t;
            if (o2xenv) {
                t *= e * e;
            }
            c2 += t;
            rsample += osc2(c2) * o2vol;

            // Noise oscillator
            if (noiseVol) {
                rsample += (2 * Math.random() - 1) * noiseVol;
            }

            // Add to (mono) channel buffer
            noteBuf[j] = (80 * rsample * e) | 0;
        }

        return noteBuf;
    };


    //--------------------------------------------------------------------------
    // Private members
    //--------------------------------------------------------------------------

    // Array of oscillator functions
    var mOscillators = [
        osc_sin,
        osc_square,
        osc_saw,
        osc_tri
    ];

    // Private variables set up by init()
    var mSong, mLastRow, mCurrentCol, mNumWords, mMixBuf;


    //--------------------------------------------------------------------------
    // Initialization
    //--------------------------------------------------------------------------

    this.init = function (song) {
        // Define the song
        mSong = song;

        // Init iteration state variables
        mLastRow = song.endPattern - 2;
        mCurrentCol = 0;

        // Prepare song info
        mNumWords =  song.rowLen * song.patternLen * (mLastRow + 1) * 2;

        // Create work buffer (initially cleared)
        mMixBuf = new Int32Array(mNumWords);
    };


    //--------------------------------------------------------------------------
    // Public methods
    //--------------------------------------------------------------------------

    // Generate audio data for a single track
    this.generate = function () {
        // Local variables
        var i, j, b, p, row, col, n, cp,
            k, t, lfor, e, x, rsample, rowStartSample, f, da;

        // Put performance critical items in local variables
        var chnBuf = new Int32Array(mNumWords),
            instr = mSong.songData[mCurrentCol],
            rowLen = mSong.rowLen,
            patternLen = mSong.patternLen;

        // Clear effect state
        var low = 0, band = 0, high;
        var lsample, filterActive = false;

        // Clear note cache.
        var noteCache = [];

         // Patterns
         for (p = 0; p <= mLastRow; ++p) {
            cp = instr.p[p];

            // Pattern rows
            for (row = 0; row < patternLen; ++row) {
                // Execute effect command.
                var cmdNo = cp ? instr.c[cp - 1].f[row] : 0;
                if (cmdNo) {
                    instr.i[cmdNo - 1] = instr.c[cp - 1].f[row + patternLen] || 0;

                    // Clear the note cache since the instrument has changed.
                    if (cmdNo < 15) {
                        noteCache = [];
                    }
                }

                // Put performance critical instrument properties in local variables
                var oscLFO = mOscillators[instr.i[15]],
                    lfoAmt = instr.i[16] / 512,
                    lfoFreq = Math.pow(2, instr.i[17] - 9) / rowLen,
                    fxLFO = instr.i[18],
                    fxFilter = instr.i[19],
                    fxFreq = instr.i[20] * 43.23529 * 3.141592 / 44100,
                    q = 1 - instr.i[21] / 255,
                    dist = instr.i[22] * 1e-5,
                    drive = instr.i[23] / 32,
                    panAmt = instr.i[24] / 512,
                    panFreq = 6.283184 * Math.pow(2, instr.i[25] - 9) / rowLen,
                    dlyAmt = instr.i[26] / 255,
                    dly = instr.i[27] * rowLen;

                // Calculate start sample number for this row in the pattern
                rowStartSample = (p * patternLen + row) * rowLen;

                // Generate notes for this pattern row
                for (col = 0; col < 4; ++col) {
                    n = cp ? instr.c[cp - 1].n[row + col * patternLen] : 0;
                    if (n) {
                        if (!noteCache[n]) {
                            noteCache[n] = createNote(instr, n, rowLen);
                        }

                        // Copy note from the note cache
                        var noteBuf = noteCache[n];
                        for (j = 0, i = rowStartSample * 2; j < noteBuf.length; j++, i += 2) {
                          chnBuf[i] += noteBuf[j];
                        }
                    }
                }

                // Perform effects for this pattern row
                for (j = 0; j < rowLen; j++) {
                    // Dry mono-sample
                    k = (rowStartSample + j) * 2;
                    rsample = chnBuf[k];

                    // We only do effects if we have some sound input
                    if (rsample || filterActive) {
                        // State variable filter
                        f = fxFreq;
                        if (fxLFO) {
                            f *= oscLFO(lfoFreq * k) * lfoAmt + 0.5;
                        }
                        f = 1.5 * Math.sin(f);
                        low += f * band;
                        high = q * (rsample - band) - low;
                        band += f * high;
                        rsample = fxFilter == 3 ? band : fxFilter == 1 ? high : low;

                        // Distortion
                        if (dist) {
                            rsample *= dist;
                            rsample = rsample < 1 ? rsample > -1 ? osc_sin(rsample*.25) : -1 : 1;
                            rsample /= dist;
                        }

                        // Drive
                        rsample *= drive;

                        // Is the filter active (i.e. still audiable)?
                        filterActive = rsample * rsample > 1e-5;

                        // Panning
                        t = Math.sin(panFreq * k) * panAmt + 0.5;
                        lsample = rsample * (1 - t);
                        rsample *= t;
                    } else {
                        lsample = 0;
                    }

                    // Delay is always done, since it does not need sound input
                    if (k >= dly) {
                        // Left channel = left + right[-p] * t
                        lsample += chnBuf[k-dly+1] * dlyAmt;

                        // Right channel = right + left[-p] * t
                        rsample += chnBuf[k-dly] * dlyAmt;
                    }

                    // Store in stereo channel buffer (needed for the delay effect)
                    chnBuf[k] = lsample | 0;
                    chnBuf[k+1] = rsample | 0;

                    // ...and add to stereo mix buffer
                    mMixBuf[k] += lsample | 0;
                    mMixBuf[k+1] += rsample | 0;
                }
            }
        }

        // Next iteration. Return progress (1.0 == done!).
        mCurrentCol++;
        return mCurrentCol / 8;
    };

    // Create a WAVE formatted Uint8Array from the generated audio data
    this.createWave = function() {
        // Create WAVE header
        var l1 = mNumWords * 2 - 8;
        var l2 = l1 - 36;
        var headerLen = 44;
        var wave = new Uint8Array(headerLen + mNumWords * 2);
        wave.set(
            [82,73,70,70,
             l1 & 255,(l1 >> 8) & 255,(l1 >> 16) & 255,(l1 >> 24) & 255,
             87,65,86,69,102,109,116,32,16,0,0,0,1,0,2,0,
             68,172,0,0,16,177,2,0,4,0,16,0,100,97,116,97,
             l2 & 255,(l2 >> 8) & 255,(l2 >> 16) & 255,(l2 >> 24) & 255]
        );

        // Append actual wave data
        for (var i = 0, idx = headerLen; i < mNumWords; ++i) {
            // Note: We clamp here
            var y = mMixBuf[i];
            y = y < -32767 ? -32767 : (y > 32767 ? 32767 : y);
            wave[idx++] = y & 255;
            wave[idx++] = (y >> 8) & 255;
        }

        // Return the WAVE formatted typed array
        return wave;
    };

    // Get n samples of wave data at time t [s]. Wave data in range [-2,2].
    this.getData = function(t, n) {
        var i = 2 * Math.floor(t * 44100);
        var d = new Array(n);
        for (var j = 0; j < 2*n; j += 1) {
            var k = i + j;
            d[j] = t > 0 && k < mMixBuf.length ? mMixBuf[k] / 32768 : 0;
        }
        return d;
    };
};

    Key = {

        _pressed: {},
        _released: {},

        LEFT: 37,
        UP: 38,
        RIGHT: 39,
        DOWN: 40,
        SPACE: 32,
        a: 65,
        w: 87,
        s: 83,
        d: 68,
        z: 90,
        x: 88,
        f: 70,
        p: 80,
        r: 82,

        isDown(keyCode) {
            return this._pressed[keyCode];
        },

        justReleased(keyCode) {
            return this._released[keyCode];
        },

        onKeydown(event) {
            this._pressed[event.keyCode] = true;
        },

        onKeyup(event) {
            this._released[event.keyCode] = true;
            delete this._pressed[event.keyCode];

        },

        update() {
            this._released = {};
        }
    };


	Txt = {
		textLine(opt) {

			var textLength = opt.text.length,
				size = 5;
			for (var i = 0; i < textLength; i++) {
				var letter = assets.letters[( opt.text.charAt(i) )] || assets.letters['unknown'];
				for (var y = 0; y < size; y++) {
					//var g = (Math.random() > opt.glitchChance) * opt.glitchFactor;
					for (var x = 0; x < size; x++) {
						if (letter[y][x] === 1) {
							//var gx = (Math.random() < gl.xch || 0) * (Math.random()-.5) * gl.xamt || 0;
							//var gy = (Math.random() < gl.ych || 0) * (Math.random()-.5) * gl.yamt || 0;

							if(opt.scale === 1){
								pset(
									opt.x + ( x * opt.scale ) + ( ( size * opt.scale ) + opt.hspacing ) * i,
									opt.y + (y * opt.scale),
									opt.color
								);
							}

							else {
								fr(
								opt.x + ( x * opt.scale ) + ( ( size * opt.scale ) + opt.hspacing ) * i,
								opt.y + (y * opt.scale),
								opt.scale,
								opt.scale,
								opt.color);
							}
								//console.log(opt.color);
						}
					}
				}
			}
		},


		text(opt) {
			var size = 5,
				letterSize = size * opt.scale,
				lines = opt.text.split('\n'),
				linesCopy = lines.slice(0),
				lineCount = lines.length,
				longestLine = linesCopy.sort(function (a, b) {
					return b.length - a.length;
				})[0],
				textWidth = ( longestLine.length * letterSize ) + ( ( longestLine.length - 1 ) * opt.hspacing ),
				textHeight = ( lineCount * letterSize ) + ( ( lineCount - 1 ) * opt.vspacing );

				if(!opt.halign)opt.halign = 'left';
				if(!opt.valign)opt.valign = 'bottom';

			var sx = opt.x,
				sy = opt.y,
				ex = opt.x + textWidth,
				ey = opt.y + textHeight;

			if (opt.halign == 'center') {
				sx = opt.x - textWidth / 2;
				ex = opt.x + textWidth / 2;
			} else if (opt.halign == 'right') {
				sx = opt.x - textWidth;
				ex = opt.x;
			}

			if (opt.valign == 'center') {
				sy = opt.y - textHeight / 2;
				ey = opt.y + textHeight / 2;
			} else if (opt.valign == 'bottom') {
				sy = opt.y - textHeight;
				ey = opt.y;
			}

			var cx = sx + textWidth / 2,
				cy = sy + textHeight / 2;

			if (opt.render) {
				for (var i = 0; i < lineCount; i++) {
					var line = lines[i],
						lineWidth = ( line.length * letterSize ) + ( ( line.length - 1 ) * opt.hspacing ),
						x = opt.x,
						y = opt.y + ( letterSize + opt.vspacing ) * i;

					if (opt.halign == 'center') {
						x = opt.x - lineWidth / 2;
					} else if (opt.halign == 'right') {
						x = opt.x - lineWidth;
					}

					if (opt.valign == 'center') {
						y = y - textHeight / 2;
					} else if (opt.valign == 'bottom') {
						y = y - textHeight;
					}

					if (opt.snap) {
						x = Math.floor(x);
						y = Math.floor(y);
					}

					this.textLine({
						ctx: opt.ctx,
						x: x,
						y: y,
						text: line,
						hspacing: opt.hspacing || 0,
						scale: opt.scale || 1,
						color: opt.color
					});
				}
			}

			return {
				sx: sx,
				sy: sy,
				cx: cx,
				cy: cy,
				ex: ex,
				ey: ey,
				width: textWidth,
				height: textHeight
			}
		}
	};

states.gameover = {

    step: function(dt) {

        if(Key.isDown(Key.r)){
          state = 'menu';
        }

    },

    render: function(dt) {

      fr(0,0,256,256, 0);

      fr(0,0,64,64,2);

      Txt.text({
              x: 128,
            y: 40 + Math.sin(t*2.5)*15,
              text: 'GAME\nOVER',
              hspacing: 8 + Math.cos(t*2.9)*4,
              vspacing: 15 + Math.sin(t*3.5)*5,
              halign: 'center',
              valign: 'top',
              scale: 10,
              snap: 1,
              render: 1,
              color: 21,
          });


    },



};

states.menu = {

    step: function(dt) {

        //game update
        if(Key.isDown(Key.p)){
          state = 'game';
        }

    },

    render: function(dt) {

      fr(0,0,256,256, 0);

      fr(0,0,64,64,2);

      Txt.text({
              x: 128,
            y: 40 + Math.sin(t*2.5)*15,
              text: 'MENU',
              hspacing: 8 + Math.cos(t*2.9)*4,
              vspacing: 15 + Math.sin(t*3.5)*5,
              halign: 'center',
              valign: 'top',
              scale: 10,
              snap: 1,
              render: 1,
              color: 21,
          });

        //draw stuff here.

    },



};

states.game = {


  step(dt) {

    player.update(dt);

    //----hacky sound test
    if(Key.justReleased(Key.z)){

      songTrigger = true
    }
    if(songTrigger){
      //  playSound(sounds.song, 1, 1, 0);
      songTrigger = false;
      incrementState();
    }
    //---end hacky sound test

    bulletPool.use();

    Key.update();
  },

  render(dt) {

    renderTarget = 0x00000;

    switch(demostate){

      case 1:
        clear(0);
        let r = 40;
        for(x=0; x < 256; x+=r){
          for( y=0; y < 256; y+=r){
            let A = x-128+Math.sin(t)*r;
            let B = y-128+Math.cos(t)*r;
            let s = Math.sqrt(A*A+B*B);
            circle(x,y, s-8, 21);
          }
        }
        renderInstructions();
      break;

      case 2:
        clear(0);
        for(let a = 0; a < 2 * Math.PI; a+= 0.7){
          for(let r = 20; r < 200; r += 9){

            let v = a + .4 * Math.sin(a*8-r/20+t);
            fillCircle((128+r*Math.cos(v)), 128+r*Math.sin(v), (10-r/12)|0, 10+(r/9%32)|0 );

          }
        }
        renderInstructions();
      break;

      case 0:
        //clear(0);
        for(let u = 0; u < 1; u+=.001){
          let x = Math.floor(128+128*Math.cos(3*u+t));
          let y = Math.floor(128+128*Math.sin(5*u+t));
          y = x^y;
          pset(x,y,u*32);
        }
        renderInstructions();
      break;

      case 3:
        clear(1);
        renderColorNumbers();
        renderDrawingAPI();
        renderInstructions();
      break;

      case 4:
        clear(1);
        let s = 128;
        let i = t/3;
        for(let y = -s; y < s; y += 3 ){
          for(let x = -s; x < s; x += 2 ){
            pset(s+x+64*Math.cos( (y/s+i)*5 )+y, s+y+64*Math.sin( (x/s+i)*5 )+x, x/8%32)
          }
        }
        renderInstructions();
      break;

      case 5:
        clear(0);
        for(let r = 0; r < 190; r+= 6){
          for(let a = 0; a < 2*Math.PI; a += 1/r*8){
            let x = r*Math.cos(a+t);
            let y = r*Math.sin(a+t);
            circle(x+128, y+128, 3+3*Math.cos(t*r/8+a*3), r/8%32)
          }
        }
        renderInstructions();
      break;

      default:
        clear(0);
        renderInstructions();
      break;


    }





  },


};

function incrementState(){
  demostate += 1;
  if(demostate > 6){
    demostate = 0;
  }
}

function renderColorNumbers(){

  for(var i = 0; i < 32; i++){
    Txt.text({
      x: i < 16 ? ( 3+16*i ) : ( 3 + 16* (i-16) ) ,
      y: i < 16 ? 8 : 8 + 16,
      text: i.toString(),
      scale: 1,
      snap: 1,
      hspacing: 1,
      vspacing: 2,
      halign: 'left',
      valign: 'bottom',
      render: 1,
      color: i,
    })
  }
}

function renderDrawingAPI(){
  pset(16*2, 16*5, 21);

  line(16*4, 16*5, 16*5, 16*7, 21);

  rect(16*6, 16*5, 16, 32, 21);

  circle(16*8, 16*6, 16, 21);
}

function renderInstructions(){


  fr(5,243,256,6,0);
  Txt.text({
    x: 5,
    y: 249,
    text: "THINGY "+ demostate + ": PRESS Z TO SEE NEXT THINGY",
    scale: 1,
    snap: 1,
    hspacing: 1,
    vspacing: 2,
    halign: 'left',
    valign: 'bottom',
    render: 1,
    color: 21,
  })


}

player = {
  // x: 0,
  // y: 0,
  // radius: 12,
  // xvel: 0,
  // yvel: 0,
  // speed: 6,
  // drag: .97,

  bullet: {
    x: 0, y:0, xvel: 0, yvel: 0
  },

  init (){
    this.x = 64;
    this.y =  230;
    this.radius = 12;
    this.xvel = 0;
    this.yvel = 0;
    this.xspeed = 400;
    this.yspeed = 400;
    this.drag = .6;
  },

  update (dt) {
    this.bullet.x = player.x;
    this.bullet.y = player.y;
    this.xvel *= player.drag;
    this.yvel *= player.drag;
    let xIntegrate = dt * player.xvel;
    let yIntegrate = dt * player.yvel;

    player.x += xIntegrate;
    player.y += yIntegrate;

    //player movement
    if (Key.isDown(Key.d) || Key.isDown(Key.RIGHT)) {
        player.xvel =  player.xspeed;
    }
    if (Key.isDown(Key.a) || Key.isDown(Key.LEFT)){
        player.xvel =  - player.xspeed;
    }
    if(Key.isDown(Key.w) || Key.isDown(Key.UP)){
      player.yvel = -player.yspeed;
    }
    if(Key.isDown(Key.s) || Key.isDown(Key.DOWN)) {
      player.yvel = player.yspeed;
    }

    if(Key.isDown(Key.SPACE || Key.isDown(Key.z))){
      //player.bullet.xvel = E.player.xvel;
      player.bullet.yvel = -350;
      bulletPool.get(player.bullet);
    }

    //world wrap for player
    if(player.x > 256){
      player.x = 0;
    }
    if(player.x < 0){
      player.x = 256;
    }
    if(player.y > 256){
      player.y = 0;
    }
    if(player.y < 0){
      state = 'gameover';
      player.y = 256;
    }
    //end world wrap for player


  },

  draw (dt) {

    // let degrees = (360/256) * E.player.x * 0.0174533;
    // let radius = (E.player.y / 2);

    // let playerDrawPoint = E.util.toPolarScreen({x:E.player.x, y:E.player.y});
    //
    // let distFromCenter = E.util.dist(playerDrawPoint.x+128, playerDrawPoint.y+128, 128,128);
    //
    // let playerSizeFactor = E.util.norm(distFromCenter, 0, 128);

    //E.renderTarget = E.screen;
    //E.gfx.fillCircle(playerDrawPoint.x+128, playerDrawPoint.y+128, E.player.radius * playerSizeFactor, 21);

    fillCircle(this.x, this.y, this.radius, 21);



  },

}


init = function(){

  last = 0;
  dt = 0;
  now = 0;
  t = 0;
  moveX = 0;
  speedFactor = .6;
  songTrigger = false;
  state = 'game';
  demostate = 0,



  bulletPool = new Pool(100, Particle);

  sounds = {};

  //stats = new Stats();
  //document.body.appendChild( stats.dom );

  starColors=[15,16,17,18,19,20,21];

  bulletPool.init();

  player.init();

  soundInit();

  eventInit();

  //init vid capture
  //capturer = new CCapture( {format: 'gif', workersPath: ''});
  //capturer.start();

  //start the game loop
  loop();

},

stopCapture = (e) => {
  //capturer.stop();
  //capturer.save();
}

loop = () => {
//  stats.begin();

  //game timer
  let now = new Date().getTime();
  dt = Math.min(1, (now - last) / 1000);
  t += dt;

  //draw current state to buffer
  states[state].render();

  //update
  states[state].step(dt);
  last = now;

  //draw buffer to screen
  render();

  //GIF capture
  //capturer.capture(C);

  //stats.end();
  requestAnimationFrame(loop);
}

soundInit = () => {

  sounds = {};
  // if(audioCtx){audioCtx.close()};
  // window.AudioContext = window.AudioContext || window.webkitAudioContext;
  // if(!audioCtx) audioCtx = new AudioContext;
  //
  // var musicplayer = new CPlayer();
  // musicplayer.init(assets.songdemo);
  // var done = false;
  // songWave = setInterval(function () {
  //   if (done) {
  //    return musicplayer.createWave();
  //   }
  //   done = musicplayer.generate() >= 1;
  // });


  //
  // let soundGen = new sonantx.MusicGenerator(assets.song);
  // soundGen.createAudioBuffer(function(buffer) {
  //   sounds.song = buffer;
  // });



}

eventInit = () => {
  //initialize keypress event listeners
  window.addEventListener('keyup', function (event) {
    Key.onKeyup(event);
  }, false);
  window.addEventListener('mousedown', function (event){
    stopCapture(event);
  }, false);
  window.addEventListener('keydown', function (event) {
    Key.onKeydown(event);
  }, false);
  window.addEventListener('blur', function (event) {
    paused = true;
  }, false);
  window.addEventListener('focus', function (event) {
    paused = false;
  }, false);
}

window.onload = init();
}
()
)

            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.
Loading ..................

Console