Created
December 2, 2014 17:37
-
-
Save rpazyaquian/d75ec905f80a8d72c019 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*global describe, it */ | |
'use strict'; | |
(function () { | |
describe('Chip8', function () { | |
describe('RAM', function () { | |
it('has 4096 bytes', function () { | |
expect(Chip8.ram.length).toEqual(4096); | |
}); | |
}); | |
describe('8-bit registers V0 - VF', function () { | |
it('initialize at 0', function () { | |
for (var i = 0; i < 16; i++) { | |
expect(Chip8.registers[i]).toEqual(0); | |
}; | |
}); | |
it('can be retrived using get(x)', function () { | |
expect(Chip8.get(0)).toEqual(0); | |
}); | |
it('can be set using set(x, nn)', function () { | |
Chip8.set(0x0, 0xFF) | |
expect(Chip8.get(0x0)).toEqual(0xFF); | |
}); | |
}); | |
describe('16-bit address register I', function () { | |
it('initializes at 0', function () { | |
expect(Chip8.index).toEqual(0); | |
}); | |
}); | |
describe('8-bit delay timer DT', function () { | |
it('initializes at 0', function () { | |
expect(Chip8.delayTimer).toEqual(0); | |
}); | |
it('ticks down at 60hz', function () { | |
Chip8.delayTimer = 60; | |
Chip8.run({seconds: 1}); | |
expect(Chip8.delayTimer).toEqual(0); | |
}); | |
}); | |
describe('8-bit sound timer ST', function () { | |
it('initializes at 0', function () { | |
expect(Chip8.soundTimer).toEqual(0); | |
}); | |
it('ticks down at 60hz', function () { | |
Chip8.soundTimer = 60; | |
Chip8.run({seconds: 1}); | |
expect(Chip8.soundTimer).toEqual(0); | |
}); | |
}); | |
describe('16-bit program counter PC', function () { | |
it('initializes at 0x200', function () { | |
expect(Chip8.programCounter).toEqual(512); | |
}); | |
}); | |
describe('8-bit stack pointer SP', function () { | |
it('initializes at 0', function () { | |
expect(Chip8.stackPointer).toEqual(0); | |
}); | |
}); | |
describe('16-bit stack', function () { | |
it('initializes at 0', function () { | |
for (var i = 0; i < 16; i++) { | |
expect(Chip8.stack[i]).toEqual(0); | |
}; | |
// what's the point of these tests? | |
// reminding me of what i need to implement, i guess | |
}); | |
}); | |
describe('display', function () { | |
it('is 64x32 pixels large', function () { | |
var width = 64; | |
var height = 32; | |
expect(Chip8.display.length).toEqual(32); | |
for (var i = 0; i < 32; i++) { | |
expect(Chip8.display[i].length).toEqual(64); | |
}; | |
}); | |
}); | |
describe('opcodes', function () { | |
var VX = Chip8.get(0); | |
var VY = Chip8.get(1); | |
var VF = Chip8.get(15); | |
describe('00E0 - CLS', function () { | |
// Clear the display. | |
it('clears the display', function () { | |
Chip8.execute(0x00E0); | |
expect(Chip8.displayIsBlank()).toBe(true); | |
}); | |
}); | |
describe('00EE - RET', function () { | |
// The interpreter sets the program counter to the address at | |
// the top of the stack, then subtracts 1 from the stack pointer. | |
it('returns from a subroutine', function () { | |
// it looks like this might depend on another | |
// function i need to test... | |
}); | |
}); | |
describe('1NNN - JP ADDR', function () { | |
// The interpreter sets the program counter to nnn. | |
it('jumps to location NNN', function () { | |
Chip8.execute(0x1200); | |
expect(Chip8.programCounter).toEqual(512); | |
}); | |
}); | |
describe('2NNN - CALL ADDR', function () { | |
// The interpreter increments the stack pointer, | |
// then puts the current PC on the top of the stack. | |
// The PC is then set to nnn. | |
it('calls subroutine at NNN', function () { | |
// NOTE: this assumes that the PC | |
// starts at 0x200, or 512. maybe don't | |
// run this test yet. | |
Chip8.execute(0x2200); | |
expect(Chip8.stackPointer).toEqual(1); | |
expect(Chip8.stack[0]).toEqual(512); | |
expect(Chip8.programCounter).toEqual(512); | |
}); | |
}); | |
describe('3XKK - SE VX, BYTE', function () { | |
// The interpreter compares register Vx to kk, | |
// and if they are equal, increments the program counter by 2. | |
it('skips next instruction if VX = KK', function () { | |
var originalCounter = Chip8.programCounter; | |
Chip8.set(0, 0x0A); | |
Chip8.execute(0x300A); | |
var newCounter = Chip8.programCounter; | |
expect(newCounter - originalCounter).toEqual(2); | |
}); | |
}); | |
describe('4XKK - SNE VX, BYTE', function () { | |
// The interpreter compares register Vx to kk, | |
// and if they are not equal, increments the program counter by 2. | |
it('skips next instruction if VX != KK', function () { | |
var originalCounter = Chip8.programCounter; | |
Chip8.set(0, 0x0A); | |
Chip8.execute(0x400B); | |
var newCounter = Chip8.programCounter; | |
expect(newCounter - originalCounter).toEqual(0); | |
}); | |
}); | |
describe('5XY0 - SE VX, VY', function () { | |
// The interpreter compares register Vx to Vy, | |
// and if they are equal, increments the program counter by 2. | |
it('skips next instruction if VX = VY', function () { | |
var originalCounter = Chip8.programCounter; | |
Chip8.set(0, 0x0A); | |
Chip8.set(1, 0x0A); | |
Chip8.execute(0x5010); | |
var newCounter = Chip8.programCounter; | |
expect(newCounter - originalCounter).toEqual(2); | |
}); | |
}); | |
describe('6XKK - LD VX, BYTE', function () { | |
// The interpreter puts the value kk into register Vx. | |
it('sets VX to KK', function () { | |
Chip8.execute(0x600A); | |
expect(Chip8.registers[0]).toEqual(0x0A); | |
}); | |
}); | |
describe('7XKK - ADD VX, BYTE', function () { | |
// Adds the value kk to the value of register Vx, | |
// then stores the result in Vx. | |
it('sets VX to (VX + KK)', function () { | |
Chip8.set(0, 0x00); | |
Chip8.execute(0x7001); | |
expect(VX).toEqual(0x01); | |
}); | |
}); | |
describe('8###', function () { | |
describe('8XY0 - LD VX, VY', function () { | |
// Stores the value of register Vy in register Vx. | |
it('sets VX to VY', function () { | |
Chip8.set(0, 0x0A); | |
Chip8.set(1, 0x14); | |
Chip8.execute(0x8010); | |
expect(VX).toEqual(VY); | |
}); | |
}); | |
describe('8XY1 - OR VX, VY', function () { | |
// Performs a bitwise OR on the values of Vx and Vy, | |
// then stores the result in Vx. A bitwise OR compares | |
// the corresponding bits from two values, and if | |
// either bit is 1, then the same bit in the result | |
// is also 1. Otherwise, it is 0. | |
it('sets VX to (VX || VY)', function () { | |
Chip8.set(0, 0x0F); | |
Chip8.set(1, 0x0A); | |
Chip8.execute(0x8011); | |
expect(VX).toEqual(0xF); | |
}); | |
}); | |
describe('8XY2 - AND VX, VY', function () { | |
// Performs a bitwise AND on the values of Vx and Vy, | |
// then stores the result in Vx. A bitwise AND compares | |
// the corrseponding bits from two values, and if | |
// both bits are 1, then the same bit in the result | |
// is also 1. Otherwise, it is 0. | |
it('sets VX to (VX && VY)', function () { | |
Chip8.set(0, 0x0F); | |
Chip8.set(1, 0x0A); | |
Chip8.execute(0x8012); | |
expect(VX).toEqual(0xA); | |
}); | |
}); | |
describe('8XY3 - XOR VX, VY', function () { | |
// Performs a bitwise XOR on the values of Vx and Vy, | |
// then stores the result in Vx. A bitwise XOR compares | |
// the corrseponding bits from two values, and if | |
// the bits are not the same, then the corresponding bit | |
// in the result is also 1. Otherwise, it is 0. | |
it('sets VX to (VX ^ VY)', function () { | |
Chip8.set(0, 0x0F); | |
Chip8.set(1, 0x0A); | |
Chip8.execute(0x8013); | |
expect(VX).toEqual(0x5); | |
}); | |
}); | |
describe('8XY4 - ADD VX, VY', function () { | |
// The values of Vx and Vy are added together. | |
// If the result is greater than 8 bits (i.e., > 255), | |
// VF is set to 1, otherwise 0. | |
// Only the lowest 8 bits of the result are kept, | |
// and stored in Vx. | |
describe('when VX + VY < 255', function () { | |
Chip8.set(0, 0x01); | |
Chip8.set(1, 0x01); | |
Chip8.execute(0x8014); | |
it('sets VX to (VX + VY)', function () { | |
expect(VX).toEqual(0x02); | |
}); | |
it('sets VF to 0', function () { | |
expect(VF).toEqual(0x00); | |
}); | |
}); | |
describe('when VX + VY > 255', function () { | |
Chip8.set(0, 0xFF); | |
Chip8.set(1, 0x01); | |
Chip8.execute(0x8014); | |
it('sets VX to (VX + VY) - 256', function () { | |
// so in this case, 0x100 = 256, | |
// therefore VX is set to 256 - 256, | |
// therefore VX = 0. | |
expect(VX).toEqual(0x00); | |
}); | |
it('sets VF to carry', function () { | |
expect(VF).toEqual(0x01); | |
}); | |
}); | |
}); | |
describe('8XY5 - SUB VX, VY', function () { | |
// If Vx > Vy, then VF is set to 1, otherwise 0. | |
// Then Vy is subtracted from Vx, | |
// and the results stored in Vx. | |
// NOTE: | |
// e.g. if Vx = 200, Vy = 100, | |
// then Vx = (200 - 100), VF = 1 | |
// if Vx = 100, Vy = 105, | |
// then Vx = 255 - abs(100-105) = 255 - 5 = 250, | |
// VF = 0. | |
// (we're assuming it rolls over.) | |
// NOTE 2: | |
// actually, that's a good point. | |
// should we assume it rolls over to | |
// the "negatives", or | |
// should it floor out at 0? | |
// let's assume it rolls over, | |
// just to be accurate... | |
// so assume that we have: | |
// VX = 0b1110 | |
// VY = 0b1111 | |
// now, counting downwards from 0b1110 | |
// we get to 0b0000, but we need to go down | |
// one more. in binary, 0b0000 - 0b0001 | |
// rolls over to 0b1111. | |
// therefore, 0b1110 - 0b1111 | |
// is equal to 0b1111, | |
// or 0xF. | |
describe('when VX > VY', function () { | |
Chip8.set(0, 0x02); | |
Chip8.set(1, 0x01); | |
Chip8.execute(0x8015); | |
it('sets VX to (VX - VY)', function () { | |
expect(VX).toEqual(0x01); | |
}); | |
it('VF to NOT borrow', function () { | |
expect(VF).toEqual(0x01); | |
// 1 if there was no "borrowing" | |
}); | |
}); | |
describe('when VX < VY', function () { | |
Chip8.set(0, 0x00); | |
Chip8.set(1, 0x01); | |
Chip8.execute(0x8015); | |
it('sets VX to (VX - VY)', function () { | |
expect(VX).toEqual(0xF); | |
}); | |
it('VF to NOT borrow', function () { | |
expect(VF).toEqual(0x0); | |
// 0 if there was "borrowing" (rollover) | |
}); | |
}); | |
describe('when VX = VY', function () { | |
// what do you do when they're the same? | |
// well, no roll-over occurs. | |
// you get VX = 0b0000, and VF = 0b1. | |
Chip8.set(0, 0x01); | |
Chip8.set(1, 0x01); | |
Chip8.execute(0x8015); | |
it('sets VX to (VX - VY)', function () { | |
expect(VX).toEqual(0x0); | |
}); | |
it('VF to NOT borrow', function () { | |
expect(VF).toEqual(0x1); | |
// 1 if there was no "borrowing" | |
}); | |
}); | |
}); | |
describe('8XY6 - SHR VX, VY', function () { | |
// If the least-significant bit of Vx is 1, | |
// then VF is set to 1, otherwise 0. | |
// Then Vx is divided by 2. | |
// NOTE: VY is ignored | |
Chip8.set(0, 0xFF); | |
Chip8.execute(0x8016); | |
it('sets VX to (VX >> 1)', function () { | |
expect(VX).toEqual(0x7F); | |
}); | |
it('VF to least-significant bit of VX (1 or 0)', function () { | |
expect(VF).toEqual(0x1); | |
}); | |
}); | |
describe('8XY7 - SUBN VX, VY', function () { | |
// If Vy > Vx, then VF is set to 1, otherwise 0. | |
// Then Vx is subtracted from Vy, | |
// and the results stored in Vx. | |
describe('when VX < VY', function () { | |
Chip8.set(0, 0xFE); | |
Chip8.set(1, 0xFF); | |
Chip8.execute(0x8017); | |
it('sets VX = (VY - VX)', function () { | |
expect(VX).toEqual(0x1); | |
}); | |
it('VF to NOT borrow', function () { | |
expect(VF).toEqual(0x1); | |
}); | |
}); | |
describe('when VX > VY', function () { | |
Chip8.set(0, 0xFF); | |
Chip8.set(1, 0xFE); | |
Chip8.execute(0x8017); | |
// assuming roll-over | |
it('sets VX = (VY - VX)', function () { | |
// VX = 0 - 1 = rollover = 255 = 0xFF | |
expect(VX).toEqual(0xFF); | |
}); | |
it('VF to NOT borrow', function () { | |
// borrowed, so VF = 0 | |
expect(VF).toEqual(0x0); | |
}); | |
}); | |
describe('when VX = VY', function () { | |
Chip8.set(0, 0xFF); | |
Chip8.set(1, 0xFE); | |
Chip8.execute(0x8017); | |
it('sets VX = (VY - VX)', function () { | |
expect(VX).toEqual(0x0); | |
}); | |
it('VF to NOT borrow', function () { | |
expect(VF).toEqual(0x1); | |
}); | |
}); | |
}); | |
describe('8XYE - SHL VX, VY', function () { | |
// If the most-significant bit of Vx is 1, | |
// then VF is set to 1, otherwise to 0. | |
// Then Vx is multiplied by 2. | |
// VX = 0x4 | |
Chip8.set(0, 0x80); | |
Chip8.execute(0x801E); | |
it('sets VX to (VX << 1)', function () { | |
// 0b 1000 0000 -> 0b 0000 0000 | |
expect(VX).toEqual(0x00); | |
}); | |
it('VF to most-significant bit of VX (1 or 0)', function () { | |
// MSB of 0b 1000 0000 is 1 | |
expect(VF).toEqual(0x01); | |
}); | |
}); | |
}); | |
describe('9XY0 - SNE VX, VY', function () { | |
// The values of Vx and Vy are compared, | |
// and if they are not equal, | |
// the program counter is increased by 2. | |
it('skips next instruction if VX != VY', function () { | |
var originalCounter = Chip8.programCounter; | |
Chip8.set(0, 0x0A); | |
Chip8.set(1, 0x0B); | |
Chip8.execute(0x5010); | |
var newCounter = Chip8.programCounter; | |
expect(newCounter - originalCounter).toEqual(2); | |
}); | |
}); | |
describe('ANNN - LD I, ADDR', function () { | |
// The value of register I is set to nnn. | |
Chip8.execute(0xA200); | |
it('sets I = NNN', function () { | |
expect(Chip8.index).toEqual(0x200); | |
}); | |
}); | |
describe('BNNN - JP V0, ADDR', function () { | |
// The program counter is set to | |
// NNN plus the value of V0. | |
Chip8.set(0, 0x01) | |
Chip8.execute(0xB200); | |
it('jumps to location NNN + V0', function () { | |
expect(Chip8.programCounter).toEqual(0x201); | |
}); | |
}); | |
describe('CXKK - RND VX, BYTE', function () { | |
// The interpreter generates a random number from 0 to 255, | |
// which is then ANDed with the value kk. | |
// The results are stored in Vx. | |
// See instruction 8xy2 for more information on AND. | |
it('sets VX = (a random byte AND KK)', function () { | |
// TODO | |
}); | |
}); | |
describe('DXYN - DRW VX, VY, NIBBLE', function () { | |
// The interpreter reads n bytes from memory, | |
// starting at the address stored in I. | |
// These bytes are then displayed as sprites | |
// on screen at coordinates (Vx, Vy). | |
// Sprites are XORed onto the existing screen. | |
// If this causes any pixels to be erased, | |
// VF is set to 1, otherwise it is set to 0. | |
// If the sprite is positioned so part of it | |
// is outside the coordinates of the display, | |
// it wraps around to the opposite side of the screen. | |
// See instruction 8xy3 for more information on XOR, | |
// and section 2.4, Display, for more information on | |
// the Chip-8 screen and sprites. | |
it('displays an N-byte (0-15 px high) sprite starting at memory location I at (Vx, Vy)', function () { | |
}); | |
it('sets VF to collision', function () { | |
}); | |
}); | |
describe('EX9E - SKP VX', function () { | |
// Checks the keyboard, and if the key | |
// corresponding to the value of Vx is currently | |
// in the down position, PC is increased by 2. | |
// NOTE: | |
// this will depend heavily on the controller | |
// provided, so don't tie it to any specific | |
// implementation! just track "[key] is up/down". | |
it('skips next instruction if key with the value of VX is pressed', function () { | |
Chip8.setKey(0, Chip8.DOWN); | |
var originalCounter = Chip8.programCounter; | |
Chip8.set(0, 0x0A); | |
Chip8.set(1, 0x0B); | |
Chip8.execute(0x5010); | |
var newCounter = Chip8.programCounter; | |
expect(newCounter - originalCounter).toEqual(2); | |
}); | |
}); | |
describe('EXA1 - SKNP VX', function () { | |
// Checks the keyboard, and if the key | |
// corresponding to the value of Vx is currently | |
// in the up position, PC is increased by 2. | |
// NOTE: | |
// this will depend heavily on the controller | |
// provided, so don't tie it to any specific | |
// implementation! just track "[key] is up/down". | |
Chip8.setKey(0, Chip8.DOWN); | |
it('skips next instruction if key with the value of VX is NOT pressed', function () { | |
}); | |
}); | |
describe('F###', function () { | |
describe('FX07 - LD VX, DT', function () { | |
// The value of DT is placed into Vx. | |
it('sets VX to value of DT', function () { | |
}); | |
}); | |
describe('FX0A - LD VX, KEY', function () { | |
// All execution stops until a key is pressed, | |
// then the value of that key is stored in Vx. | |
it('waits for a key press', function () { | |
}); | |
it('sets VX to value of pressed key', function () { | |
}); | |
}); | |
describe('FX15 - LD DT, VX', function () { | |
// DT is set equal to the value of Vx. | |
it('sets DT to value of VX', function () { | |
}); | |
}); | |
describe('FX18 - LD ST, VX', function () { | |
// ST is set equal to the value of Vx. | |
it('sets ST to value of VX', function () { | |
}); | |
}); | |
describe('FX1E - ADD I, VX', function () { | |
// The values of I and Vx are added, | |
// and the results are stored in I. | |
it('sets I to (I + VX)', function () { | |
}); | |
}); | |
describe('FX29 - LD F, VX', function () { | |
// The value of I is set to the location for | |
// the hexadecimal sprite corresponding to | |
// the value of Vx. See section 2.4, Display, | |
// for more information on the | |
// Chip-8 hexadecimal font. | |
it('sets I to location of sprite for digit VX', function () { | |
}); | |
}); | |
describe('FX33 - LD B, VX', function () { | |
// The interpreter takes the decimal value of Vx, | |
// and places the hundreds digit in memory at | |
// location in I, the tens digit at location | |
// I+1, and the ones digit at location I+2. | |
it('stores hundreds digit of VX in memory at I', function () { | |
}); | |
it('stores tens digit of VX in memory at I+1', function () { | |
}); | |
it('stores ones digit of VX in memory at I+2', function () { | |
}); | |
}); | |
describe('FX55 - LD [I], VX', function () { | |
// The interpreter copies the values of registers V0 | |
// through VX into memory, starting at the address in I. | |
// NOTE: | |
// so for example, `F855` would get the contents of | |
// V0, V1, V2 ... V8 (9 total) and copy them into | |
// RAM at I, I+1, I+2 ... I+8 in order. | |
it('stores registers V0 through VX in memory starting at I', function () { | |
}); | |
}); | |
describe('FX65 - LD VX, [I]', function () { | |
// The interpreter reads values from memory starting | |
// at location I into registers V0 through Vx. | |
// NOTE: | |
// so for example, `F865` would get the contents in RAM | |
// at I, I+1, I+2 ... I+8 (9 total) and copy them | |
// to V0, V1, V2 ... V8 in order. | |
it('reads registers V0 through VX from memory starting at I', function () { | |
}); | |
}); | |
}); | |
}); | |
describe('auxiliary logic', function () { | |
it('should run here few assertions', function () { | |
}); | |
}); | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment