Skip to content

Commit

Permalink
iterate
Browse files Browse the repository at this point in the history
  • Loading branch information
shicks committed Jan 8, 2016
1 parent c5b495f commit baffe7a
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 27 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
test4.compiled.js: bufferedaudionode.js stepgeneratornode.js test4.js Makefile
{ java -jar ~/Downloads/compiler.jar --js=bufferedaudionode.js --js=stepgeneratornode.js --js=test4.js --language_in=ES6_STRICT --language_out=ES5_STRICT --create_source_map=test4.srcmap --jscomp_warning=checkTypes --jscomp_warning=checkVars; echo "//# sourceMappingURL=test4.srcmap"; } >| test4.compiled.js

nes.compiled.js: clock.js mem.js apu/apu.js apu/pulse.js apu/envelope.js cpu.js nsf.js stepgeneratornode.js bufferedaudionode.js nsfplayer.js Makefile
{ java -jar ~/Downloads/compiler.jar --js=clock.js --js=mem.js --js=apu/apu.js --js=apu/pulse.js --js=apu/envelope.js --js=cpu.js --js=nsf.js --js=bufferedaudionode.js --js=stepgeneratornode.js --js=nsfplayer.js --language_in=ES6_STRICT --language_out=ES5_STRICT --create_source_map=nes.srcmap --jscomp_warning=checkTypes --jscomp_warning=checkVars; echo "//# sourceMappingURL=nes.srcmap"; } >| nes.compiled.js
nes.compiled.js: clock.js mem.js apu/lengthcounter.js apu/envelope.js apu/pulse.js apu/apu.js cpu.js nsf.js stepgeneratornode.js bufferedaudionode.js nsfplayer.js Makefile
{ java -jar ~/Downloads/compiler.jar --js=clock.js --js=mem.js --js=apu/lengthcounter.js --js=apu/envelope.js --js=apu/pulse.js --js=apu/apu.js --js=cpu.js --js=nsf.js --js=bufferedaudionode.js --js=stepgeneratornode.js --js=nsfplayer.js --language_in=ES6_STRICT --language_out=ES5_STRICT --create_source_map=nes.srcmap --jscomp_warning=checkTypes --jscomp_warning=checkVars; echo "//# sourceMappingURL=nes.srcmap"; } >| nes.compiled.js
18 changes: 14 additions & 4 deletions apu/envelope.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Memory from '../mem';
import LengthCounter from './lengthcounter';

/** Envelope generator (TODO - inherit from LengthCounter?). */
export default class Envelope {
Expand All @@ -13,13 +14,12 @@ export default class Envelope {
this.constantVolume_ = mem.bool(base, 4);
/** @private @const {!Memory.Register<boolean>} */
this.loopFlag_ = mem.bool(base, 5); // TODO(sdh): also: length counter halt?
// /** @private @const {!Memory.Register<number>} */
// this.lengthCounter_ = mem.int(base + 3, 3, 5);

mem.listen(base + 3, () => {
// console.log('envelope start: ' + mem.get(base + 3));
// window.msg = true;
this.start_ = true;
if (!this.loopFlag_.get()) this.lengthCounter_.start();
});

/** @private {boolean} */
Expand All @@ -28,24 +28,32 @@ export default class Envelope {
this.divider_ = 0;
/** @private {number} */
this.counter_ = 0;

/** @private {!LengthCounter} */
this.lengthCounter_ = new LengthCounter(mem, base);
}

print() {
return `
volumeEnvelope=${this.volumeEnvelope_.get()}
constantVolume=${this.constantVolume_.get()}
loopFlag=${this.loopFlag_.get()}`;
// TODO -include length counter
}

/** Clocked by the frame counter. */
clock() {
/**
* Clocked by the frame counter.
* @param {number} half Whether this is a half frame.
*/
clock(half) {
if (!this.start_) {
this.clockDivider_();
} else {
this.start_ = false;
this.counter_ = 15;
this.reloadDivider_();
}
if (half && !this.loopFlag_.get()) this.lengthCounter_.clock();
}

clockDivider_() {
Expand All @@ -68,6 +76,8 @@ export default class Envelope {

/** Returns the volume. */
volume() {
// First check the length counter
if (!this.loopFlag_.get() && !this.lengthCounter_.enabled()) return 0;
if (this.constantVolume_.get()) {
//console.log('constant volume: ' + this.volumeEnvelope_.get());
return this.volumeEnvelope_.get();
Expand Down
40 changes: 40 additions & 0 deletions apu/lengthcounter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export default class LengthCounter {
constructor(mem, base) {
/** @private @const {!Memory.Register<boolean>} */
this.enabled_ = mem.bool(0x4015, (base >>> 2) & 7);
/** @private @const {!Memory.Register<number>} */
this.reload_ = mem.int(base + 3, 3, 5);
/** @private {number} */
this.counter_ = 0;

mem.listen(0x4015, () => { if (!this.enabled_.get()) this.disable(); });
}

clock() {
if (this.counter_ > 0) this.counter_--;
}

start() {
if (this.enabled_.get()) {
this.counter_ = LengthCounter.LENGTHS[this.reload_.get()];
}
}

disable() {
this.counter_ = 0;
}

/** @return {boolean} */
enabled() {
return !!this.counter_;
}
}


/**
* List of lengths.
* @const {!Array<number>}
*/
LengthCounter.LENGTHS = [
10,254, 20, 2, 40, 4, 80, 6, 160, 8, 60, 10, 14, 12, 26, 14,
12, 16, 24, 18, 48, 20, 96, 22, 192, 24, 72, 26, 16, 28, 32, 30];
14 changes: 7 additions & 7 deletions apu/pulse.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ export default class ApuPulse {
this.sweepEnabled_ = mem.bool(base, 15);
/** @private @const {!Memory.Register<number>} */
this.wavePeriod_ = mem.int(base, 16, 11);
/** @private @const {!Memory.Register<number>} */
this.lengthCounter_ = mem.int(base, 27, 5);

/** @private {number} */
this.sweepDivider_ = 0; // TODO(sdh): use a Divider?
Expand Down Expand Up @@ -59,8 +57,7 @@ pulse ${this.base_ - 0x4000}: silenced=${this.silenced_}, duty=${DUTY_CYCLE_LIST
sweepNegate=${this.sweepNegate_.get()}
sweepPeriod=${this.sweepPeriod_.get()}
sweepEnabled=${this.sweepEnabled_.get()}
wavePeriod=${this.wavePeriod_.get()}
lengthCounter=${this.lengthCounter_.get()}` + this.envelope_.print());
wavePeriod=${this.wavePeriod_.get()}` + this.envelope_.print());
}

/**
Expand All @@ -78,8 +75,11 @@ pulse ${this.base_ - 0x4000}: silenced=${this.silenced_}, duty=${DUTY_CYCLE_LIST
return this.envelope_.volume();
}

/** Clocks the frame counter. */
clockFrame() {
/**
* Clocks the frame counter.
* @param {number} quarter An integer from 0 to 3, indicating the quarter.
*/
clockFrame(quarter) {
if (this.sweepDivider_ == 0 && this.sweepEnabled_.get()) {
const target = this.sweepTarget_();
if (target > 0x7ff || target < 8) {
Expand All @@ -94,7 +94,7 @@ pulse ${this.base_ - 0x4000}: silenced=${this.silenced_}, duty=${DUTY_CYCLE_LIST
this.sweepDivider_ = this.sweepPeriod_.get();
this.sweepReload_ = false;
}
this.envelope_.clock();
this.envelope_.clock(quarter % 2);
}

/** Clocks the sequencer. */
Expand Down
40 changes: 32 additions & 8 deletions cpu.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ export default class Cpu {
try {
this.opcode.op.call(this);
} finally {
if (window.msg) { console.log(this.message); window.msg = false; }
if (window.msg) {
console.log(this.message);
window.msg = false; }
}

if (!this.opcode.extraCycles) this.wait = 0;
Expand All @@ -85,10 +87,14 @@ export default class Cpu {

disassemble(addr, count) {
const result = [];
this.PC = addr - 1;
this.PC = --addr;
while (count-- > 0) {
this.loadOp();
result.push(this.message);
let bytes = '\t\t\t';
while (addr < this.PC) {
bytes += hex(this.mem_.get(++addr)).substring(1) + ' ';
}
result.push(this.message + bytes);
}
console.log(result.join('\n'));
}
Expand Down Expand Up @@ -323,7 +329,6 @@ export default class Cpu {
BRK() { this.B = this.I = 1; }



get MP() {
const addr = this.opcode.mode.func.call(this);
if (addr == null || addr < 0) throw new Error('Jump to non-address.');
Expand Down Expand Up @@ -355,23 +360,29 @@ export default class Cpu {

/** @param {number} value A one-byte integer. */
pushByte(value) {
this.mem_[this.SP--] = value;
this.mem_.set(this.SP--, value);
this.message += `\t\t(SP)=${hex(value)}, SP=${hex(this.SP,2)}`;
}

/** @param {number} value A two-byte integer. */
pushWord(value) {
this.mem_.setWord(this.SP - 1, value);
this.SP -= 2;
this.message += `\t\t(SP)=${hex(value, 2)}, SP=${hex(this.SP,2)}`;
}

/** @return {number} */
pullByte(value) {
return this.mem_[++this.SP];
const result = this.mem_.get(++this.SP);
this.message += `\t\t${hex(result)}<-(SP), SP=${hex(this.SP,2)}`;
return result;
}

/** @return {number} */
pullWord(value) {
return this.mem_.getWord((this.SP += 2) - 1);
const result = this.mem_.getWord((this.SP += 2) - 1);
this.message += `\t\t${hex(result, 2)}<-(SP), SP=${hex(this.SP,2)}`;
return result;
}

/**
Expand Down Expand Up @@ -406,7 +417,7 @@ export default class Cpu {
* @private
*/
checkBranch_(addr) {
this.message += `\t\tPC=${hex(this.PC, 2)}`;
this.message += `\t\tPC=${hex(this.PC, 2)}->${hex(addr, 2)}`;
this.wait = ((this.PC & 0xf000) == (addr & 0xf000)) ? 1 : 2;
return addr;
}
Expand Down Expand Up @@ -563,7 +574,14 @@ function instructionTable() {
op('NOP', Cpu.prototype.NOP);
op('BRK', Cpu.prototype.BRK);
// Illegal Opcodes
function combo(a, b) {
if (!a || !b) throw new Error('bad reference');
return function() { a.call(this); b.call(this); };
}
op('KIL', Cpu.prototype.KIL);
op('SLO', combo(Cpu.prototype.ASL, Cpu.prototype.ORA));
op('XAA', combo(Cpu.prototype.TXA, Cpu.prototype.AND));
op('RLA', combo(Cpu.prototype.ROL, Cpu.prototype.AND));

// Addressing Modes
mode('A', Cpu.prototype.accumulator);
Expand Down Expand Up @@ -670,6 +688,7 @@ function instructionTable() {
let illegal = false;
if (split[0][3] == '!') {
split[0] = split[0].replace('!', '');
split[0] = split[0].replace('!', ''); // some have two
illegal = true;
}
let op = ops[split[0]];
Expand Down Expand Up @@ -699,6 +718,11 @@ function instructionTable() {
}

function hex(num, opt_bytes, opt_signed) {
if (num == null) {
window.msg = true;
setTimeout(() => { throw 'NULL number'; }, 0);
return 'NUL';
}
let sign = '';
if (opt_signed) {
sign = '+';
Expand Down
9 changes: 5 additions & 4 deletions mem.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default class Memory {
const reg = this.registers_[addr];
if (reg) reg.set(value);
else this.data8_[addr] = value;
this.call_(addr);
this.call_(addr, value);
}


Expand All @@ -64,21 +64,22 @@ export default class Memory {

/**
* @param {number} addr
* @param {number} value
* @private
*/
call_(addr) {
call_(addr, value) {
const cbs = this.callbacks_[addr];
if (cbs) {
for (let cb of cbs) {
cb();
cb(value);
}
}
}


/**
* @param {number} addr
* @param {function()} callback
* @param {function(number)} callback
*/
listen(addr, callback) {
(this.callbacks_[addr] = this.callbacks_[addr] || []).push(callback);
Expand Down
1 change: 1 addition & 0 deletions nsf.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export default class Nsf {
cpu.pushWord(this.playAddress_ - 1);
cpu.PC = this.initAddress_ - 1;
cpu.A = song || this.startSong_;
cpu.X = 0; // or PAL...
}

frame(cpu) {
Expand Down
6 changes: 4 additions & 2 deletions nsfplayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default class NsfPlayer {
//yield [];
let frameCounter = this.cyclesPerFrame;
// console.log('Starting frame counter at ' + frameCounter);
for (let i = 0; i < 600 * this.cyclesPerFrame; i++) {
for (let i = 0; /*i < 6 * this.cyclesPerFrame*/; i++) {
if (frameCounter != frameCounter) throw new Error('NaN');
if (--frameCounter <= 0) {
frameCounter = this.cyclesPerFrame;
Expand All @@ -35,7 +35,8 @@ export default class NsfPlayer {
this.nsf.frame(this.cpu);
}
// Yield a single frame worth of steps
const data = this.apu.steps();
let data = this.apu.steps();
if (!data.length) data = [[this.clock.time, 0]];
// console.log('Yield data', data);
yield data;
}
Expand All @@ -62,6 +63,7 @@ function startEmu(buf) {
console.log(nsf + '');
const ac = new AudioContext();
const player = new NsfPlayer(ac, nsf);
window.PLAYER = player;

let track = 1;

Expand Down

0 comments on commit baffe7a

Please sign in to comment.