Initial Commit
This commit is contained in:
commit
e3fbf385f8
13 changed files with 314 additions and 0 deletions
BIN
bin/chip/Chip.class
Normal file
BIN
bin/chip/Chip.class
Normal file
Binary file not shown.
BIN
bin/chip/ChipData.class
Normal file
BIN
bin/chip/ChipData.class
Normal file
Binary file not shown.
BIN
bin/emu/ChipFrame.class
Normal file
BIN
bin/emu/ChipFrame.class
Normal file
Binary file not shown.
BIN
bin/emu/ChipPanel.class
Normal file
BIN
bin/emu/ChipPanel.class
Normal file
Binary file not shown.
BIN
bin/emu/Main.class
Normal file
BIN
bin/emu/Main.class
Normal file
Binary file not shown.
BIN
res/invaders.c8
Normal file
BIN
res/invaders.c8
Normal file
Binary file not shown.
BIN
res/pong2.c8
Normal file
BIN
res/pong2.c8
Normal file
Binary file not shown.
BIN
res/tetris.c8
Normal file
BIN
res/tetris.c8
Normal file
Binary file not shown.
190
src/chip/Chip.java
Normal file
190
src/chip/Chip.java
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
package chip;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class Chip {
|
||||||
|
|
||||||
|
private char[] memory;
|
||||||
|
private char[] V;
|
||||||
|
private char I;
|
||||||
|
private char pc;
|
||||||
|
|
||||||
|
private char stack[];
|
||||||
|
private int stackPointer;
|
||||||
|
|
||||||
|
private int delay_timer;
|
||||||
|
private int sound_timer;
|
||||||
|
|
||||||
|
private byte[] keys;
|
||||||
|
|
||||||
|
private byte[] display;
|
||||||
|
|
||||||
|
private boolean needRedraw;
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
memory = new char[4096];
|
||||||
|
V = new char[16];
|
||||||
|
I = 0x0;
|
||||||
|
pc = 0x200;
|
||||||
|
|
||||||
|
stack = new char[16];
|
||||||
|
stackPointer = 0;
|
||||||
|
|
||||||
|
delay_timer = 0;
|
||||||
|
sound_timer = 0;
|
||||||
|
|
||||||
|
keys = new byte[16];
|
||||||
|
|
||||||
|
display = new byte[64 * 32];
|
||||||
|
|
||||||
|
needRedraw = false;
|
||||||
|
loadFontset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
//fetch opcode
|
||||||
|
char opcode = (char)((memory[pc] << 8) | memory[pc + 1]);
|
||||||
|
System.out.println("Opcode: " + Integer.toHexString(opcode).toUpperCase());
|
||||||
|
//decode opcode
|
||||||
|
switch(opcode & 0xF000) {
|
||||||
|
|
||||||
|
case 0x1000: {
|
||||||
|
System.err.println("Unsupported Opcode!");
|
||||||
|
System.exit(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x2000: {
|
||||||
|
stack[stackPointer] = pc;
|
||||||
|
stackPointer++;
|
||||||
|
pc = (char)(opcode & 0x0FFF);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x3000: {
|
||||||
|
int x = (opcode & 0x0F00) >> 8;
|
||||||
|
int nn = (opcode & 0x00FF);
|
||||||
|
if (V[x] == nn) {
|
||||||
|
pc += 4;
|
||||||
|
System.out.println("VX = NN: Skipping 4");
|
||||||
|
} else {
|
||||||
|
pc += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x6000: {
|
||||||
|
int index = (opcode & 0x0F00) >> 8;
|
||||||
|
V[index] = (char)(opcode & 0x00FF);
|
||||||
|
pc += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x7000: {
|
||||||
|
int x = (opcode & 0x0F00) >> 8;
|
||||||
|
int nn = (opcode & 0x00FF);
|
||||||
|
V[x] = (char)((V[x] + nn) & 0xFF);
|
||||||
|
pc += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x8000: //Contains more data in last nibble
|
||||||
|
|
||||||
|
switch(opcode & 0x000F) {
|
||||||
|
|
||||||
|
case 0x0000: //8XY0: Sets VX to the value of VY.
|
||||||
|
default:
|
||||||
|
System.err.println("Unsupported Opcode!");
|
||||||
|
System.exit(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xA000: {
|
||||||
|
I = (char)(opcode & 0x0FFF);
|
||||||
|
pc += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0xD000: {
|
||||||
|
int x = V[(opcode & 0x0F00) >> 8];
|
||||||
|
int y = V[(opcode & 0x00F0) >> 4];
|
||||||
|
int height = opcode & 0x000F;
|
||||||
|
|
||||||
|
V[0xF] = 0;
|
||||||
|
|
||||||
|
for (int _y=0;_y<height;_y++) {
|
||||||
|
int line = memory[I + _y];
|
||||||
|
for (int _x=0;_x<8;_x++) {
|
||||||
|
int pixel = line & (0x80 >> _x);
|
||||||
|
if (pixel != 0) {
|
||||||
|
int totalX = _x + _x;
|
||||||
|
int totalY = y + _y;
|
||||||
|
int index = totalY * 64 + totalX;
|
||||||
|
|
||||||
|
if (display[index] == 1)
|
||||||
|
V[0xF] = 1;
|
||||||
|
|
||||||
|
display[index] ^= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pc += 2;
|
||||||
|
needRedraw = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
System.err.println("Unsupported Opcode!");
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
//execute opcode
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getDisplay() {
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean needsRedraw() {
|
||||||
|
return needRedraw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeDrawFlag() {
|
||||||
|
needRedraw = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadProgram(String file) {
|
||||||
|
DataInputStream input = null;
|
||||||
|
try {
|
||||||
|
input = new DataInputStream(new FileInputStream(new File(file)));
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
while(input.available() > 0) {
|
||||||
|
memory[0x200 + offset] = (char)(input.readByte() & 0xFF);
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//for (int offset = 0; input.available() > 0; offset++) {
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.exit(0);
|
||||||
|
} finally {
|
||||||
|
if(input != null) {
|
||||||
|
try { input.close(); } catch (IOException ex) {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadFontset() {
|
||||||
|
for (int i=0;i < ChipData.fontset.length;i++) {
|
||||||
|
memory[0x50 + i] = (char)(ChipData.fontset[i] & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
src/chip/ChipData.java
Normal file
29
src/chip/ChipData.java
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package chip;
|
||||||
|
|
||||||
|
public class ChipData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fontset in bytes
|
||||||
|
* Memory position 0x50
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static int[] fontset =
|
||||||
|
{
|
||||||
|
0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
|
||||||
|
0x20, 0x60, 0x20, 0x20, 0x70, // 1
|
||||||
|
0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
|
||||||
|
0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
|
||||||
|
0x90, 0x90, 0xF0, 0x10, 0x10, // 4
|
||||||
|
0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
|
||||||
|
0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
|
||||||
|
0xF0, 0x10, 0x20, 0x40, 0x40, // 7
|
||||||
|
0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
|
||||||
|
0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
|
||||||
|
0xF0, 0x90, 0xF0, 0x90, 0x90, // A
|
||||||
|
0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
|
||||||
|
0xF0, 0x80, 0x80, 0x80, 0xF0, // C
|
||||||
|
0xE0, 0x90, 0x90, 0x90, 0xE0, // D
|
||||||
|
0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
|
||||||
|
0xF0, 0x80, 0xF0, 0x80, 0x80 // F
|
||||||
|
};
|
||||||
|
}
|
27
src/emu/ChipFrame.java
Normal file
27
src/emu/ChipFrame.java
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package emu;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
|
||||||
|
import chip.Chip;
|
||||||
|
|
||||||
|
public class ChipFrame extends JFrame {
|
||||||
|
|
||||||
|
private ChipPanel panel;
|
||||||
|
|
||||||
|
public ChipFrame(Chip c) {
|
||||||
|
setPreferredSize(new Dimension(640, 320));
|
||||||
|
pack();
|
||||||
|
setPreferredSize(new Dimension(640 + getInsets().left + getInsets().right, 320 + getInsets().top + getInsets().bottom));
|
||||||
|
panel = new ChipPanel(c);
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
add(panel, BorderLayout.CENTER);
|
||||||
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
setTitle("Chip 8 Emulator");
|
||||||
|
pack();
|
||||||
|
setLocationRelativeTo(null);
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
src/emu/ChipPanel.java
Normal file
32
src/emu/ChipPanel.java
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package emu;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import chip.Chip;
|
||||||
|
|
||||||
|
public class ChipPanel extends JPanel {
|
||||||
|
|
||||||
|
private Chip chip;
|
||||||
|
|
||||||
|
public ChipPanel(Chip chip) {
|
||||||
|
this.chip = chip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void paint(Graphics g) {
|
||||||
|
byte[] display = chip.getDisplay();
|
||||||
|
for (int i=0;i<display.length;i++) {
|
||||||
|
if (display[i] == 0)
|
||||||
|
g.setColor(Color.BLACK);
|
||||||
|
else
|
||||||
|
g.setColor(Color.WHITE);
|
||||||
|
|
||||||
|
int x = (i % 64);
|
||||||
|
int y = (int)Math.floor(i / 64);
|
||||||
|
|
||||||
|
g.fillRect(x * 10, y * 10, 10, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
src/emu/Main.java
Normal file
36
src/emu/Main.java
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
package emu;
|
||||||
|
|
||||||
|
import chip.Chip;
|
||||||
|
|
||||||
|
public class Main extends Thread {
|
||||||
|
|
||||||
|
private Chip chip8;
|
||||||
|
private ChipFrame frame;
|
||||||
|
|
||||||
|
public Main() {
|
||||||
|
chip8 = new Chip();
|
||||||
|
chip8.init();
|
||||||
|
chip8.loadProgram("res/pong2.c8");
|
||||||
|
frame = new ChipFrame(chip8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
while(true) {
|
||||||
|
chip8.run();
|
||||||
|
if (chip8.needsRedraw()) {
|
||||||
|
frame.repaint();
|
||||||
|
chip8.removeDrawFlag();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(16);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Main main = new Main();
|
||||||
|
main.start();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue