├── .travis.yml ├── examples ├── mario.chr └── mario-demo.js ├── .gitignore ├── bin └── nesly ├── lib ├── banking.js ├── colors.json ├── header.js ├── joy.js ├── palettes.js ├── std.js ├── sprites.js └── bg.js ├── tests ├── bg.js ├── header.js ├── sprites.js └── joy.js ├── README.md ├── package.json └── index.js /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | -------------------------------------------------------------------------------- /examples/mario.chr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emkay/nesly/HEAD/examples/mario.chr -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | node_modules 15 | npm-debug.log -------------------------------------------------------------------------------- /bin/nesly: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var nesly = require('../'); 4 | var fs = require('fs'); 5 | 6 | 7 | var file = fs.readFileSync(process.argv[2], 'utf-8'); 8 | var output = nesly.compile(file); 9 | 10 | fs.writeFileSync(process.argv[3], output); 11 | -------------------------------------------------------------------------------- /lib/banking.js: -------------------------------------------------------------------------------- 1 | function bank(arguments) { 2 | var n = arguments[0]; 3 | var loc = arguments[1]; 4 | var code = arguments[2]; 5 | 6 | var output = []; 7 | output.push('\t.bank ' + n); 8 | output.push('\t.org ' + loc); 9 | output.push(code); 10 | return output.join('\n'); 11 | } 12 | 13 | module.exports = bank; 14 | -------------------------------------------------------------------------------- /tests/bg.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | var bgLib = require('../lib/bg'); 3 | 4 | test("make sure we write hello world", function (t) { 5 | bgLib.write('hello world'); 6 | t.equal('\t.db 17,14,21,21,24,36,32,24,27,21,13,36,36,36,36,36', 7 | bgLib.background[0], 8 | "Expected hello world"); 9 | t.end() 10 | }); 11 | -------------------------------------------------------------------------------- /tests/header.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | var headerLib = require('../lib/header'); 3 | 4 | test("make sure header is correct", function (t) { 5 | 6 | var expected = "\t.inesprg 1\n\t.ineschr 1\n\t.inesmap 0\n\t.inesmir 1"; 7 | var output = headerLib({prg:1, chr:1, map:0, mir:1}); 8 | 9 | t.equal(output, expected, "the header was not the expected result"); 10 | t.end(); 11 | }); 12 | -------------------------------------------------------------------------------- /lib/colors.json: -------------------------------------------------------------------------------- 1 | { 2 | "gray": "$00", 3 | "lightGray": "$10", 4 | "lighterGrey": "$20", 5 | "white": "$30", 6 | "darkBlue": "$01", 7 | "lightBlue": "$11", 8 | "lighterBlue": "$21", 9 | "blue": "$12", 10 | "purple": "$03", 11 | "lightPurple": "$13", 12 | "lighterPurple": "$23", 13 | "black": "$0F", 14 | "red": "$06", 15 | "green": "$1A", 16 | "lightGreen": "$2A", 17 | "orange": "$26", 18 | "yellow": "$38" 19 | } 20 | -------------------------------------------------------------------------------- /lib/header.js: -------------------------------------------------------------------------------- 1 | module.exports = function (o) { 2 | if (!o) { 3 | throw new Error("Header object is required sucker!"); 4 | } 5 | 6 | var output = []; 7 | var prg = o.prg; 8 | var chr = o.chr; 9 | var map = o.map; 10 | var mir = o.mir; 11 | 12 | output.push('\t.inesprg ' + prg); 13 | output.push('\t.ineschr ' + chr); 14 | output.push('\t.inesmap ' + map); 15 | output.push('\t.inesmir ' + mir); 16 | return output.join('\n'); 17 | }; 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | nesly 2 | ===== 3 | 4 | A programming language that compiles down to 6502 NES assembler 5 | 6 | [![Build Status](https://travis-ci.org/emkay/nesly.png?branch=master)](https://travis-ci.org/emkay/nesly) 7 | 8 | ## Install 9 | `npm i -g nesly` 10 | 11 | ## Examples 12 | Take a look at the `mario-demo.js` file. There is a lot of stuff hardcoded in asm to get the example working. It's not really ready to use for creating anything useful. 13 | 14 | To get the example running you need [nesasm](http://www.nespowerpak.com/nesasm/) and a [nes emulator](https://duckduckgo.com/?q=nes+emulator). 15 | 16 | ``` 17 | nesly mario-demo.js mario-test.s; 18 | nesasm mario-test.s; 19 | open mario-test.nes; 20 | ``` 21 | 22 | ![nesly demo](https://dl.dropboxusercontent.com/u/476602/nesly-demo.png) 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nesly", 3 | "version": "0.3.1", 4 | "description": "Ever want to program a NES game?", 5 | "main": "index.js", 6 | "bin": { 7 | "nesly": "./bin/nesly" 8 | }, 9 | "directories": { 10 | "example": "examples" 11 | }, 12 | "dependencies": { 13 | "falafel": "~0.3.1" 14 | }, 15 | "devDependencies": { 16 | "tap": "~0.4.4" 17 | }, 18 | "scripts": { 19 | "test": "tap tests/*.js" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "git://github.com/emkay/nesly.git" 24 | }, 25 | "keywords": [ 26 | "nes", 27 | "game", 28 | "language" 29 | ], 30 | "author": "Michael Matuzak ", 31 | "license": "BSD", 32 | "bugs": { 33 | "url": "https://github.com/emkay/nesly/issues" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/joy.js: -------------------------------------------------------------------------------- 1 | function init() { 2 | return [ 3 | '\tlda #$01', 4 | '\tsta $4016', 5 | '\tlda #$00', 6 | '\tsta $4016' 7 | ].join('\n'); 8 | } 9 | 10 | function read(o) { 11 | if (!o) { 12 | throw new Error('Argument must be an object'); 13 | } 14 | 15 | if (!o.label) { 16 | throw new Error('Object must have a `label` key'); 17 | } 18 | 19 | var label = o.label; 20 | var fn = o && o.cb; 21 | var done = o && o.done; 22 | 23 | var output = [ 24 | label+':', 25 | '\tlda $4016', 26 | '\tand #%00000001', 27 | '\tbeq '+label+'Done' 28 | ]; 29 | 30 | if (fn) { 31 | output.push(fn()); 32 | } 33 | 34 | output.push(label+'Done'+':'); 35 | if (done) { 36 | output.push(done()); 37 | } 38 | 39 | return output.join('\n'); 40 | } 41 | 42 | module.exports.init = init; 43 | module.exports.read = read; 44 | -------------------------------------------------------------------------------- /tests/sprites.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | var spriteLib = require('../lib/sprites'); 3 | 4 | test("make sure addData is adding sprite data", function (t) { 5 | var expected = [ 6 | 'sprites:', 7 | '\t.db $80, 32, $00, $80', 8 | '\t.db $80, 33, $00, $88', 9 | '\t.db $88, 34, $00, $80', 10 | '\t.db $88, 35, $00, $88'].join('\n'); 11 | 12 | // x, y, tile, attr 13 | spriteLib.addData({x: '80', 14 | y: '80', 15 | tile: '32', 16 | attr:'00'}); 17 | 18 | spriteLib.addData({x: '88', 19 | y: '80', 20 | tile: '33', 21 | attr: '00'}); 22 | 23 | spriteLib.addData({x: '80', 24 | y: '88', 25 | tile: '34', 26 | attr: '00'}); 27 | 28 | spriteLib.addData({x: '88', 29 | y: '88', 30 | tile: '35', 31 | attr: '00'}); 32 | 33 | t.equal(spriteLib.sData(), expected, "sData should return expected sprite data"); 34 | t.end(); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/joy.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | var joyLib = require('../lib/joy'); 3 | 4 | test("make sure the controller works", function (t) { 5 | var error; 6 | 7 | var expected = "ReadA:\n\tlda $4016\n\tand #%00000001\n\tbeq ReadADone\ntest\nReadADone:"; 8 | var output = joyLib.read({label: 'ReadA', cb: function () { return 'test'; }}); 9 | t.equal(output, expected, "ReadA did not produce the expected output"); 10 | 11 | output = joyLib.read({label: 'ReadB', cb: function () { return 'test'; }}); 12 | expected = "ReadB:\n\tlda $4016\n\tand #%00000001\n\tbeq ReadBDone\ntest\nReadBDone:"; 13 | t.equal(output, expected, "ReadB did not produce the expected output"); 14 | 15 | 16 | try { 17 | joyLib.read(); 18 | } catch (e) { 19 | error = {name: e.name, message: e.message}; 20 | } 21 | 22 | t.ok(error, "Error was not thrown"); 23 | 24 | t.equal('Error', error.name); 25 | t.equal('Argument must be an object', error.message); 26 | t.end(); 27 | }); 28 | -------------------------------------------------------------------------------- /lib/palettes.js: -------------------------------------------------------------------------------- 1 | var paletteData = {}; 2 | 3 | paletteData.bg = '\t.db $22,$29,$1A,$0F,$22,$36,$17,$0F,$22,$30,$21,$0F,$22,$27,$17,$0F'; 4 | paletteData.sprite = '\t.db $0F,$16,$27,$18,$22,$02,$38,$3C,$22,$1C,$15,$14,$22,$02,$38,$3C'; 5 | 6 | function setLowHighBytes() { 7 | return [ 8 | '\tlda $2002', 9 | '\tlda #$3F', 10 | '\tsta $2006', 11 | '\tlda #$00', 12 | '\tsta $2006' 13 | ].join('\n'); 14 | } 15 | 16 | function pData() { 17 | return ['PaletteData:', 18 | paletteData.bg, 19 | paletteData.sprite 20 | ].join('\n'); 21 | } 22 | 23 | function loadPalette() { 24 | return [ 25 | '\tldx #$00', 26 | 'LoadPalettesLoop:', 27 | '\tlda PaletteData, x', 28 | '\tsta $2007', 29 | '\tinx', 30 | '\tcpx #$20', 31 | '\tbne LoadPalettesLoop' 32 | ].join('\n'); 33 | } 34 | 35 | module.exports.palette = function () { 36 | return [ 37 | //pData(), 38 | setLowHighBytes(), 39 | loadPalette() 40 | ].join('\n'); 41 | }; 42 | 43 | module.exports.pData = pData; 44 | -------------------------------------------------------------------------------- /lib/std.js: -------------------------------------------------------------------------------- 1 | var bank = require('./banking'); 2 | 3 | function reset() { 4 | var code = [ 5 | 'RESET:', 6 | '\tsei', 7 | '\tcld', 8 | '\tldx #$40', 9 | '\tstx $4017', 10 | '\tldx #$FF', 11 | '\ttxs', 12 | '\tinx', 13 | '\tstx $2000', 14 | '\tstx $2001', 15 | '\tstx $4010' 16 | ].join('\n'); 17 | 18 | return bank([0, '$C000', code]); 19 | } 20 | 21 | function vec() { 22 | return [ 23 | '\t.dw NMI', 24 | '\t.dw RESET', 25 | '\t.dw 0' 26 | ].join('\n'); 27 | } 28 | 29 | function vblankwait(arguments) { 30 | var n = arguments[0]; 31 | return [ 32 | 'vblankwait'+n+':', 33 | '\tbit $2002', 34 | '\tbpl vblankwait'+n 35 | ].join('\n'); 36 | } 37 | 38 | function clrmem() { 39 | return [ 40 | 'clrmem:', 41 | '\tlda #$00', 42 | '\tsta $0000, x', 43 | '\tsta $0100, x', 44 | '\tsta $0200, x', 45 | '\tsta $0400, x', 46 | '\tsta $0500, x', 47 | '\tsta $0600, x', 48 | '\tsta $0700, x', 49 | '\tlda #$FE', 50 | '\tsta $0300, x', 51 | '\tinx', 52 | '\tbne clrmem' 53 | ].join('\n'); 54 | } 55 | 56 | module.exports.reset = reset; 57 | module.exports.vec = vec; 58 | module.exports.vblankwait = vblankwait; 59 | module.exports.clrmem = clrmem; 60 | -------------------------------------------------------------------------------- /lib/sprites.js: -------------------------------------------------------------------------------- 1 | var spriteData = []; 2 | 3 | function setLowHighBytes() { 4 | return [ 5 | '\tlda #$00', 6 | '\tsta $2003', 7 | '\tlda #$02', 8 | '\tsta $4014' 9 | ].join('\n'); 10 | } 11 | 12 | function loadSprites() { 13 | return [ 14 | 'LoadSprites:', 15 | '\tldx #$00', 16 | 'LoadSpritesLoop:', 17 | '\tlda sprites, x', 18 | '\tsta $0200, x', 19 | '\tinx', 20 | '\tcpx #$10', 21 | '\tbne LoadSpritesLoop' 22 | ].join('\n'); 23 | } 24 | 25 | function addData(data) { 26 | var x = data.x; 27 | var y = data.y; 28 | var tile = data.tile; 29 | var attr = data.attr; 30 | 31 | var sprite = '\t.db $' 32 | +y 33 | +', ' 34 | +tile 35 | +', $' 36 | +attr 37 | +', $' 38 | +x; 39 | spriteData.push(sprite); 40 | } 41 | 42 | /** 43 | '\t.db $80, $32, $00, $80', 44 | '\t.db $80, $33, $00, $88', 45 | '\t.db $88, $34, $00, $80', 46 | '\t.db $88, $35, $00, $88' 47 | */ 48 | function sData() { 49 | var out = 'sprites:\n'; 50 | out += spriteData.join('\n'); 51 | return out; 52 | } 53 | 54 | function moveRight() { 55 | return [ 56 | '\tlda $0203', 57 | '\tclc', 58 | '\tadc #$01', 59 | '\tsta $0203', 60 | 61 | '\tlda $0207', 62 | '\tclc', 63 | '\tadc #$01', 64 | '\tsta $0207', 65 | 66 | '\tlda $020B', 67 | '\tclc', 68 | '\tadc #$01', 69 | '\tsta $020B', 70 | 71 | '\tlda $020F', 72 | '\tclc', 73 | '\tadc #$01', 74 | '\tsta $020F' 75 | ].join('\n'); 76 | } 77 | 78 | function moveLeft() { 79 | return [ 80 | '\tlda $0203', 81 | '\tsec', 82 | '\tsbc #$01', 83 | '\tsta $0203', 84 | 85 | '\tlda $0207', 86 | '\tsec', 87 | '\tsbc #$01', 88 | '\tsta $0207', 89 | 90 | '\tlda $020B', 91 | '\tsec', 92 | '\tsbc #$01', 93 | '\tsta $020B', 94 | 95 | '\tlda $020F', 96 | '\tsec', 97 | '\tsbc #$01', 98 | '\tsta $020F' 99 | ].join('\n'); 100 | } 101 | 102 | function moveDown() { 103 | return [ 104 | '\tlda $0200', 105 | '\tclc', 106 | '\tadc #$01', 107 | '\tsta $0200', 108 | 109 | '\tlda $0204', 110 | '\tclc', 111 | '\tadc #$01', 112 | '\tsta $0204', 113 | 114 | '\tlda $0208', 115 | '\tclc', 116 | '\tadc #$01', 117 | '\tsta $0208', 118 | 119 | '\tlda $020C', 120 | '\tclc', 121 | '\tadc #$01', 122 | '\tsta $020C' 123 | ].join('\n'); 124 | } 125 | 126 | function moveUp() { 127 | return [ 128 | '\tlda $0200', 129 | '\tsec', 130 | '\tsbc #$01', 131 | '\tsta $0200', 132 | 133 | '\tlda $0204', 134 | '\tsec', 135 | '\tsbc #$01', 136 | '\tsta $0204', 137 | 138 | '\tlda $0208', 139 | '\tsec', 140 | '\tsbc #$01', 141 | '\tsta $0208', 142 | 143 | '\tlda $020C', 144 | '\tsec', 145 | '\tsbc #$01', 146 | '\tsta $020C' 147 | 148 | 149 | 150 | ].join('\n'); 151 | } 152 | 153 | module.exports.loadSprites = loadSprites; 154 | module.exports.sData = sData; 155 | module.exports.setLowHighBytes = setLowHighBytes; 156 | module.exports.moveRight = moveRight; 157 | module.exports.moveLeft = moveLeft; 158 | module.exports.moveUp = moveUp; 159 | module.exports.moveDown = moveDown; 160 | module.exports.addData = addData; 161 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var falafel = require('falafel'); 3 | 4 | var std = require('./lib/std'); 5 | var header = require('./lib/header'); 6 | var bank = require('./lib/banking'); 7 | var palette = require('./lib/palettes'); 8 | var sprites = require('./lib/sprites'); 9 | var bg = require('./lib/bg.js'); 10 | var joy = require('./lib/joy'); 11 | 12 | var TOKENS = { 13 | 'reset': std.reset, 14 | 'vec': std.vec, 15 | 'vblankwait': std.vblankwait, 16 | 'clrmem': std.clrmem, 17 | 'header': header, 18 | 'bank': bank, 19 | 'palette': palette.palette, 20 | 'pData': palette.pData, 21 | 'addData': sprites.addData, 22 | 'loadSprites': sprites.loadSprites, 23 | 'sData': sprites.sData, 24 | 'setLowHighBytes': sprites.setLowHighBytes, 25 | 'moveRight': sprites.moveRight, 26 | 'moveLeft': sprites.moveLeft, 27 | 'moveUp': sprites.moveUp, 28 | 'moveDown': sprites.moveDown, 29 | 'enableBg': bg.enableBg, 30 | 'loadAttribute': bg.loadAttribute, 31 | 'addBg': bg.addBgRow, 32 | 'loadBg': bg.loadBg, 33 | 'write': bg.write, 34 | 'attributeTable': bg.attributeTable, 35 | 'loadNametable': bg.loadNametable, 36 | 'joyInit': joy.init, 37 | 'joyRead': joy.read, 38 | 'asm': function (exp) { return exp; } 39 | }; 40 | 41 | function expressionStatement(node) { 42 | var callee = node.expression.callee; 43 | var args = []; 44 | var name; 45 | var fn; 46 | var o; 47 | 48 | var argumentFn = function (arg) { 49 | var value; 50 | 51 | if (arg.type === 'ObjectExpression') { 52 | value = {}; 53 | arg.properties.forEach(function (p) { 54 | var k = p.key.name; 55 | var v; 56 | 57 | if (p.value.type === 'Identifier') { 58 | v = TOKENS[p.value.name]; 59 | } else { 60 | v = p.value.value; 61 | } 62 | 63 | value[k] = v; 64 | o = value; 65 | }); 66 | } else { 67 | if (arg.name) { 68 | if (TOKENS[arg.name]) { 69 | value = TOKENS[arg.name]; 70 | } 71 | } else { 72 | value = arg.value; 73 | } 74 | args.push(value); 75 | } 76 | }; 77 | 78 | if (callee && callee.name) { 79 | name = callee.name; 80 | } 81 | 82 | if (name) { 83 | fn = TOKENS[name]; 84 | callee.parent.arguments.forEach(argumentFn); 85 | 86 | if (fn) { 87 | if (o) { 88 | node.update(fn(o)); 89 | delete o; 90 | } else { 91 | node.update(fn(args)); 92 | } 93 | } 94 | } 95 | } 96 | 97 | function variableDeclarator(node) { 98 | var name = node && node.id && node.id.name; 99 | var value = node && node.init && node.init.value; 100 | var label = 'var_'+name+':\t'; 101 | 102 | var updatedValue; 103 | 104 | switch (value) { 105 | case true: 106 | updatedValue = 1; 107 | break; 108 | case false: 109 | updatedValue = 0; 110 | break; 111 | default: 112 | updatedValue = value; 113 | } 114 | 115 | if (node.parent && node.parent.kind === 'var') { 116 | node.parent.update(''); 117 | } 118 | 119 | node.update(label + '.db\t' + updatedValue); 120 | } 121 | 122 | var TYPES = { 123 | 'ExpressionStatement': expressionStatement, 124 | 'VariableDeclarator': variableDeclarator 125 | }; 126 | 127 | 128 | function compiler(node) { 129 | if (TYPES[node.type]) { 130 | TYPES[node.type](node); 131 | } 132 | } 133 | 134 | module.exports.compile = function (file) { 135 | var output = falafel(file, compiler); 136 | return output; 137 | }; 138 | -------------------------------------------------------------------------------- /lib/bg.js: -------------------------------------------------------------------------------- 1 | var alphaNum = { 2 | "0": 0, 3 | "1": 1, 4 | "2": 2, 5 | "3": 3, 6 | "4": 4, 7 | "5": 5, 8 | "6": 6, 9 | "7": 7, 10 | "8": 8, 11 | "9": 9, 12 | "a": 10, 13 | "b": 11, 14 | "c": 12, 15 | "d": 13, 16 | "e": 14, 17 | "f": 15, 18 | "g": 16, 19 | "h": 17, 20 | "i": 18, 21 | "j": 19, 22 | "k": 20, 23 | "l": 21, 24 | "m": 22, 25 | "n": 23, 26 | "o": 24, 27 | "p": 25, 28 | "q": 26, 29 | "r": 27, 30 | "s": 28, 31 | "t": 29, 32 | "u": 30, 33 | "v": 31, 34 | "w": 32, 35 | "x": 33, 36 | "y": 34, 37 | "z": 35, 38 | " ": 36 39 | }; 40 | 41 | var background = []; 42 | 43 | function addBgRow() { 44 | var row = arguments[0]; 45 | background.push('\t.db '+row); 46 | } 47 | 48 | function write() { 49 | var s = arguments[0]; 50 | var out = []; 51 | 52 | if (typeof s === 'object') { 53 | s = s.pop(); 54 | } 55 | s.split('').forEach(function (c) { 56 | out.push(alphaNum[c]); 57 | }); 58 | 59 | while (out.length - 1 < 15) { 60 | out.push('36'); 61 | } 62 | 63 | addBgRow(out.join(',')); 64 | } 65 | 66 | function loadNametable() { 67 | return [ 68 | 'background1:', 69 | background.slice(0,15).join('\n'), 70 | 'background2:', 71 | background.slice(16,31).join('\n'), 72 | 'background3:', 73 | background.slice(32,47).join('\n'), 74 | 'background4:', 75 | background.slice(48,63).join('\n') 76 | ].join('\n'); 77 | } 78 | 79 | function attributeTable() { 80 | return [ 81 | 'attribute:', 82 | 83 | '\t.db %00010001, %00010001, %01010101, %00010001, %00010001, %00010001, %00010001, %01110111', 84 | '\t.db %00010001, %00010001, %01010101, %00010001, %00010001, %00010001, %00010001, %01110111', 85 | 86 | '\t.db %00010001, %00010001, %01010101, %00010001, %00010001, %00010001, %00010001, %01110111', 87 | '\t.db %00010001, %00010001, %01010101, %00010001, %00010001, %00010001, %00010001, %01110111', 88 | 89 | '\t.db %00010001, %00010001, %01010101, %00010001, %00010001, %00010001, %00010001, %01110111', 90 | '\t.db %00010001, %00010001, %01010101, %00010001, %00010001, %00010001, %00010001, %01110111', 91 | 92 | '\t.db %00010001, %00010001, %01010101, %00010001, %00010001, %00010001, %00010001, %01110111', 93 | '\t.db %00010001, %00010001, %01010101, %00010001, %00010001, %00010001, %00010001, %01110111' 94 | ].join('\n'); 95 | } 96 | 97 | function loadBg() { 98 | return [ 99 | 'LoadBackgrounds:', 100 | '\tlda $2002', 101 | '\tlda #$20', 102 | '\tsta $2006', 103 | '\tlda #$00', 104 | '\tsta $2006', 105 | '\tldx #$00', 106 | 'LoadBackground1:', 107 | '\tlda background1, x', 108 | '\tsta $2007', 109 | '\tinx', 110 | '\tcpx #$00', 111 | '\tbne LoadBackground1', 112 | 'LoadBackground2:', 113 | '\tlda background2, x', 114 | '\tsta $2007', 115 | '\tinx', 116 | '\tcpx #$00', 117 | '\tbne LoadBackground2', 118 | 'LoadBackground3:', 119 | '\tlda background3, x', 120 | '\tsta $2007', 121 | '\tinx', 122 | '\tcpx #$00', 123 | '\tbne LoadBackground3', 124 | 'LoadBackground4:', 125 | '\tlda background4, x', 126 | '\tsta $2007', 127 | '\tinx', 128 | '\tcpx #$00', 129 | '\tbne LoadBackground4' 130 | ].join('\n'); 131 | } 132 | 133 | function loadAttribute() { 134 | return [ 135 | 'LoadAttribute:', 136 | '\tlda $2002', 137 | '\tlda #$23', 138 | '\tsta $2006', 139 | '\tlda #$C0', 140 | '\tsta $2006', 141 | '\tldx #$00', 142 | 'LoadAttributeLoop:', 143 | '\tlda attribute, x', 144 | '\tsta $2007', 145 | '\tinx', 146 | '\tcpx #$40', 147 | '\tbne LoadAttributeLoop' 148 | ].join('\n'); 149 | } 150 | 151 | function enableBg() { 152 | return [ 153 | '\tlda #%10010000', 154 | '\tsta $2000', 155 | '\tlda #%00011110', 156 | '\tsta $2001', 157 | '\tlda #$00', 158 | '\tsta $2005', 159 | '\tsta $2005' 160 | ].join('\n'); 161 | } 162 | 163 | module.exports.enableBg = enableBg; 164 | module.exports.loadAttribute = loadAttribute; 165 | module.exports.loadBg = loadBg; 166 | module.exports.attributeTable = attributeTable; 167 | module.exports.loadNametable = loadNametable; 168 | 169 | module.exports.addBgRow = addBgRow; 170 | module.exports.write = write; 171 | module.exports.background = background; 172 | -------------------------------------------------------------------------------- /examples/mario-demo.js: -------------------------------------------------------------------------------- 1 | header({prg: 1, chr: 1, map: 0, mir: 1}); 2 | 3 | reset(); 4 | vblankwait(1); 5 | clrmem(); 6 | vblankwait(2); 7 | 8 | palette(); 9 | loadSprites(); 10 | 11 | loadBg(); 12 | loadAttribute(); 13 | 14 | asm('\tLDA #%10010000'); 15 | asm('\tSTA $2000'); 16 | asm('\tLDA #%00011110'); 17 | asm('\tSTA $2001'); 18 | asm('Forever:'); 19 | asm('\tJMP Forever'); 20 | asm('NMI:'); 21 | 22 | setLowHighBytes(); 23 | 24 | joyInit(); 25 | joyRead({label: 'ReadA'}); 26 | joyRead({label: 'ReadB'}); 27 | joyRead({label: 'ReadSel'}); 28 | joyRead({label: 'ReadStart'}); 29 | joyRead({label: 'ReadUp', cb: moveUp}); 30 | joyRead({label: 'ReadDown', cb: moveDown}); 31 | joyRead({label: 'ReadLeft', cb: moveLeft}); 32 | joyRead({label: 'ReadRight', cb: moveRight, done: enableBg}); 33 | 34 | asm('\trti'); 35 | asm('\t.bank 1'); 36 | asm('\t.org $E000'); 37 | 38 | pData(); 39 | 40 | addData({x: '80', y: '80', tile: '112', attr: '0'}); 41 | addData({x: '88', y: '80', tile: '113', attr: '0'}); 42 | addData({x: '80', y: '88', tile: '114', attr: '0'}); 43 | addData({x: '88', y: '88', tile: '115', attr: '0'}); 44 | sData(); 45 | 46 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 47 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 48 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 49 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 50 | addBg('$24,$24,$24,$24,$45,$45,$24,$24,$45,$45,$45,$45,$45,$45,$24,$24'); 51 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$53,$54,$24,$24'); 52 | addBg('$24,$24,$24,$24,$47,$47,$24,$24,$47,$47,$47,$47,$47,$47,$24,$24'); 53 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$55,$56,$24,$24'); 54 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 55 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 56 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 57 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 58 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 59 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 60 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 61 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 62 | 63 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 64 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 65 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 66 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 67 | addBg('$24,$24,$24,$24,$45,$45,$24,$24,$45,$45,$45,$45,$45,$45,$24,$24'); 68 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$53,$54,$24,$24'); 69 | addBg('$24,$24,$24,$24,$47,$47,$24,$24,$47,$47,$47,$47,$47,$47,$24,$24'); 70 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$55,$56,$24,$24'); 71 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 72 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 73 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 74 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 75 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 76 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 77 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 78 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 79 | 80 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 81 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 82 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 83 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 84 | addBg('$24,$24,$24,$24,$45,$45,$24,$24,$45,$45,$45,$45,$45,$45,$24,$24'); 85 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$53,$54,$24,$24'); 86 | addBg('$24,$24,$24,$24,$47,$47,$24,$24,$47,$47,$47,$47,$47,$47,$24,$24'); 87 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$55,$56,$24,$24'); 88 | write('hello world'); 89 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 90 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 91 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 92 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 93 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 94 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 95 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 96 | 97 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 98 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 99 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 100 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 101 | addBg('$24,$24,$24,$24,$45,$45,$24,$24,$45,$45,$45,$45,$45,$45,$24,$24'); 102 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$53,$54,$24,$24'); 103 | addBg('$24,$24,$24,$24,$47,$47,$24,$24,$47,$47,$47,$47,$47,$47,$24,$24'); 104 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$55,$56,$24,$24'); 105 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 106 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 107 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 108 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 109 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 110 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 111 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 112 | addBg('$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24'); 113 | 114 | 115 | loadNametable(); 116 | attributeTable(); 117 | 118 | asm('\t.org $FFFA'); 119 | 120 | vec(); 121 | bank(2, '$0000', '\t.incbin "mario.chr"'); 122 | --------------------------------------------------------------------------------