Initial Commit

This commit is contained in:
Sebastian Cabrera 2020-07-26 11:20:59 -04:00
commit e3fbf385f8
13 changed files with 314 additions and 0 deletions

BIN
bin/chip/Chip.class Normal file

Binary file not shown.

BIN
bin/chip/ChipData.class Normal file

Binary file not shown.

BIN
bin/emu/ChipFrame.class Normal file

Binary file not shown.

BIN
bin/emu/ChipPanel.class Normal file

Binary file not shown.

BIN
bin/emu/Main.class Normal file

Binary file not shown.

BIN
res/invaders.c8 Normal file

Binary file not shown.

BIN
res/pong2.c8 Normal file

Binary file not shown.

BIN
res/tetris.c8 Normal file

Binary file not shown.

190
src/chip/Chip.java Normal file
View 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
View 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
View 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
View 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
View 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();
}
}