Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
A Chip-8 emulator written in JavaScript (Node.js).
Chip-8 is a simple, interpreted, programming language which was first used on some do-it-yourself computer systems in the late 1970s and early 1980s.
Chip8.js is an ongoing project by Tania Rascia to write a Chip-8 emulator in JavaScript. The main motivation is to learn lower level programming concepts, detailed here, and to increase familiarity with the JavaScript and the Node.js environment.
Concepts I learned while writing this program:
&
), OR (|
), XOR (^
), left shift (<<
), right shift (>>
) and how to use them for masking, setting, and testing valuesArticles I wrote based on aforementioned concepts:
This guide assumes you already have Node.js and Yarn installed.
The only dependency of Chip8.js is jest for testing. Run yarn
to install.
yarn
Chip-8 compatible ROMs can be saved in the roms/
directory. A copy of Connect 4 is shipped with Chip8.js (at roms/CONNECT4
) for example and testing purposes.
Create a ROM buffer of a ROM and load the data into the CPU. Execute the program.
yarn start roms/<ROM>
View a 16-bit hex dump of a ROM. (View more information on bits, bytes, bases, and hex dumps).
yarn hexdump roms/<ROM>
The output will look something like this (using CONNECT4
as an example).
000000 121a 434f 4e4e 4543 5434 2062 7920 4461
000010 7669 6420 5749 4e54 4552 a2bb f665 a2b4
000020 f655 6900 6801 6b00 6d0f 6e1f a2a5 600d
000030 6132 6200 d02f d12f 720f 321e 1234 d021
000040 d121 7201 600a a29f d021 d121 a29f dde1
000050 fc0a dde1 4c05 127e 3c04 126a 7bff 7dfb
000060 3d0a 127a 6b06 6d2d 127a 3c06 1298 7b01
000070 7d05 3d32 127a 6b00 6d0f dde1 1250 a2b4
000080 fb1e f065 40fc 1298 8a00 70fb f055 8983
000090 a29e 3900 a2a1 dda4 a29f dde1 1250 60f0
0000a0 f060 9090 6080 8080 8080 8080 8080 8080
0000b0 8080 8080 1a1a 1a1a 1a1a 1a1a 1a1a 1a1a
0000c0 1a1a
The source code is contained in the classes/
and constants/
directories. Chip8.js comes with a single ROM, a few helper scripts, and unit tests.
chip8/
classes/
CPU.js
Disassembler.js
RomBuffer.js
constants/
fontSet.js
instructionSet.js
roms/
CONNECT4
scripts/
hexdump.js
<more>
tests/
cpu.test.js
instructions.test.js
.gitignore
index.js
LICENSE
package.json
README.md
yarn.lock
In progress.
The unit tests for Chip8.js use the Jest testing framework. You can run all test suites with or without displaying coverage.
# Run test suites
yarn test
# Run test suites and view coverage
yarn test --coverage
Chip8.js has two suites of unit tests:
The instruction tests cover the INSTRUCTION_SET
found in constants/instructionSet.js
. Each instruction has:
key
: for internal useid
: for a unique namename
: for the type of instruction)mask
: to filter out arguments from instruction signifiers)pattern
: to match the mask to the specific instruction patternarguments
, each of which contain:
mask
: to filter the nibble(s) to argumentsshift
: to shift it by locationtype
: to signify the type of argument{
key: 6,
id: 'SE_VX_NN',
name: 'SE',
mask: 0xf000,
pattern: 0x3000,
arguments: [{ mask: 0x0f00, shift: 8, type: 'R' }, { mask: 0x00ff, shift: 0, type: 'NN' }],
}
Each unit test checks an opcode to an instruction and tests:
id
to ensure the correct instruction is running for the mask/patterntest('test instruction 06: 3xkk - SE Vx, byte', () => {
expect(Disassembler.disassemble(0x3abb).instruction).toHaveProperty('id', 'SE_VX_NN')
expect(Disassembler.disassemble(0x3abb).args).toHaveLength(2)
expect(Disassembler.disassemble(0x3abb).args[0]).toBe(0xa)
expect(Disassembler.disassemble(0x3abb).args[1]).toBe(0xbb)
})
There are 35 instruction tests for 35 opcodes (the first instruction, CLS
, is no longer implemented).
The CPU decodes the opcode and returns the instruction object from constants/instructionSet.js
. Each instruction performs a specific, unique action in the case
. The CPU tests test the state of the CPU after an executing an instruction.
In the below example, the instruction is skipping an instruction if Vx === kk
, otherwise it's going to the next instruction as usual.
case 'SE_VX_NN':
// Skip next instruction if Vx = kk.
if (this.registers[args[0]] === args[1]) {
this._skipInstruction()
} else {
this._nextInstruction()
}
break
Each CPU test:
RomBuffer
containing the data of a single opcodestep
methodIn this example, the instruction can either be skipped or not skipped depending on the arguments, and both cases are tested.
test('test cpu 06: 3xkk - SE Vx, byte', () => {
cpu.load({ data: [0x3abb] })
cpu.step()
expect(cpu.PC).toBe(0x202)
cpu.load({ data: [0x3abb] })
cpu.registers[0xa] = 0xbb
cpu.step()
expect(cpu.PC).toBe(0x204)
})
The code is open source and available under the MIT License.
Written by Tania Rascia.
FAQs
A Chip-8 emulator written in JavaScript (for Node.js and the web).
We found that chip8js demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.