Skip to content

Commit f0123b1

Browse files
author
Antigravity
committed
Move all files from chip8_local to the root directory
1 parent 59e8849 commit f0123b1

29 files changed

+631
-0
lines changed

Chip8.java

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Another Chip8 emulator - For educational purposes
3+
* 2018 - Javier Crespo
4+
*
5+
* https://en.wikipedia.org/wiki/CHIP-8 // Description
6+
* http://devernay.free.fr/hacks/chip8/C8TECH10.HTM // Technical Reference
7+
* http://www.multigesture.net/articles/how-to-write-an-emulator-chip-8-interpreter/
8+
*
9+
*/
10+
//package es.javiercrespo;
11+
12+
import java.io.File;
13+
import java.io.FileInputStream;
14+
import java.io.IOException;
15+
16+
import javax.swing.JFrame;
17+
18+
//import org.apache.commons.io.IOUtils;
19+
20+
21+
22+
public class Chip8 {
23+
24+
private static Cpu cpu;
25+
private static Display display;
26+
private static Keyboard keyboard;
27+
private static ProcesingUnit pu;
28+
private static Sprite sprites;
29+
30+
public static void main(String[] args) throws InterruptedException {
31+
32+
cpu = new Cpu();
33+
display = new Display();
34+
display.setScreen(cpu.screen);
35+
keyboard = new Keyboard();
36+
pu = new ProcesingUnit(cpu, keyboard, display);
37+
sprites = new Sprite();
38+
39+
40+
init();
41+
42+
String romPath = "roms/INVADERS";
43+
if (args.length > 0) {
44+
romPath = args[0];
45+
} else {
46+
System.out.println("No ROM specified. Loading default: roms/INVADERS");
47+
System.out.println("Usage: java Chip8 [path_to_rom]");
48+
}
49+
50+
loadRom(romPath);
51+
//cpu.dumpMemory();
52+
prepareGUI();
53+
54+
boolean end = false;
55+
56+
57+
while (!end) {
58+
pu.run();
59+
//end = true;
60+
}
61+
62+
63+
64+
}
65+
66+
private static void init() {
67+
68+
cpu.sp = cpu.i = cpu.dt = cpu.st = 0x00;
69+
cpu.pc = 0x200;
70+
71+
for (int i=0; i<cpu.memory.length;i++) cpu.memory[i] = 0x00;
72+
for (int i=0; i<cpu.screen.length;i++) cpu.screen[i] = 0x00;
73+
for (int i=0; i<cpu.stack.length;i++) cpu.stack[i] = 0x00;
74+
for (int i=0; i<cpu.v.length;i++) cpu.v[i] = 0x00;
75+
76+
System.arraycopy(sprites.sprites, 0, cpu.memory, 0x50, sprites.sprites.length);//Sprites
77+
display.addKeyListener(keyboard);
78+
79+
}
80+
81+
82+
private static void loadRom(String romPath) {
83+
84+
File file = new File(romPath);
85+
FileInputStream fis = null;
86+
87+
try {
88+
fis = new FileInputStream(file);
89+
//byte[] data = IOUtils.toByteArray(fis);
90+
byte[] data = fis.readAllBytes();
91+
int currentOffset = 0x200;
92+
for (byte theByte : data) {
93+
cpu.memory[currentOffset] = (short) (theByte & 0xFF);
94+
currentOffset++;
95+
}
96+
System.out.println("Successfully loaded ROM: " + romPath);
97+
} catch (Exception e) {
98+
System.err.println("Error loading ROM: " + e.getMessage());
99+
} finally {
100+
if (fis != null) {
101+
try {
102+
fis.close();
103+
} catch (IOException e) {
104+
System.out.println(e.getMessage());
105+
}
106+
}
107+
}
108+
109+
}
110+
111+
112+
private static void prepareGUI(){
113+
JFrame f = new JFrame("CHIP-8 emulator");
114+
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
115+
f.add(display);
116+
f.pack();
117+
f.setResizable(false);
118+
f.setVisible(true);
119+
f.addKeyListener(keyboard);
120+
121+
}
122+
123+
}

Cpu.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//package es.javiercrespo;
2+
3+
import java.util.Random;
4+
5+
public class Cpu {
6+
7+
public short[] memory = new short[4096]; // Main memory
8+
public short[] v = new short[16]; // Registers v
9+
public short i; // I register
10+
public short dt, st; // Delay Timer & Sound Timer registers
11+
public short pc; // Program Counter
12+
public short[] stack = new short[16]; // Stack
13+
public short sp; // Stack pointer (value to save in stack array)
14+
public Random rnd = new Random();
15+
public short[] screen = new short[2048]; // Screen memory
16+
17+
public void dumpMemory() {
18+
for (int i = 0; i < memory.length; i++) {
19+
System.out.println(String.format("%03X", i) + " : " + String.format("%08X", memory[i]));
20+
}
21+
}
22+
}

Display.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//package es.javiercrespo;
2+
3+
import java.awt.Color;
4+
import java.awt.Dimension;
5+
import java.awt.Graphics;
6+
import java.awt.event.KeyEvent;
7+
import java.awt.event.KeyListener;
8+
import java.awt.image.BufferStrategy;
9+
10+
import javax.swing.JFrame;
11+
import javax.swing.JPanel;
12+
13+
public class Display extends JPanel {
14+
15+
private static final long serialVersionUID = -5606672764531745977L;
16+
private int SCALE = 10;
17+
private int FIL = 32;
18+
private int COL = 64;
19+
private short[] screen;
20+
boolean drawFlag;
21+
22+
public Display() {
23+
setBackground(Color.BLACK);
24+
}
25+
26+
public void setScreen(short[] screen) {
27+
this.screen = screen;
28+
}
29+
30+
@Override
31+
public Dimension getPreferredSize() {
32+
return new Dimension(COL * SCALE, FIL * SCALE);
33+
}
34+
35+
@Override
36+
protected void paintComponent(Graphics g) {
37+
super.paintComponent(g);
38+
39+
if (screen == null) return;
40+
41+
for (int y = 0; y < FIL; y++) {
42+
for (int x = 0; x < COL; x++) {
43+
if ((screen[x + (y * COL)] & 0xFF) == 1) {
44+
g.setColor(Color.WHITE);
45+
} else {
46+
g.setColor(Color.BLACK);
47+
}
48+
g.fillRect(x * SCALE, y * SCALE, SCALE, SCALE);
49+
}
50+
}
51+
}
52+
}

Keyboard.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//package es.javiercrespo;
2+
3+
import java.awt.event.KeyAdapter;
4+
import java.awt.event.KeyEvent;
5+
6+
public class Keyboard extends KeyAdapter {
7+
8+
private boolean[] keys = new boolean[16];
9+
private int lastKeyPressed = -1;
10+
11+
public static final int[] KeyCodeMap = {
12+
KeyEvent.VK_X, // Key 0
13+
KeyEvent.VK_1, // Key 1
14+
KeyEvent.VK_2, // Key 2
15+
KeyEvent.VK_3, // Key 3
16+
KeyEvent.VK_Q, // Key 4
17+
KeyEvent.VK_W, // Key 5
18+
KeyEvent.VK_E, // Key 6
19+
KeyEvent.VK_A, // Key 7
20+
KeyEvent.VK_S, // Key 8
21+
KeyEvent.VK_D, // Key 9
22+
KeyEvent.VK_Z, // Key A
23+
KeyEvent.VK_C, // Key B
24+
KeyEvent.VK_4, // Key C
25+
KeyEvent.VK_R, // Key D
26+
KeyEvent.VK_F, // Key E
27+
KeyEvent.VK_V, // Key F
28+
};
29+
30+
@Override
31+
public void keyPressed(KeyEvent e) {
32+
int key = mapKeycodeToChip8Key(e.getKeyCode());
33+
if (key != -1) {
34+
keys[key] = true;
35+
lastKeyPressed = key;
36+
}
37+
}
38+
39+
@Override
40+
public void keyReleased(KeyEvent e) {
41+
int key = mapKeycodeToChip8Key(e.getKeyCode());
42+
if (key != -1) {
43+
keys[key] = false;
44+
}
45+
}
46+
47+
public int mapKeycodeToChip8Key(int keycode) {
48+
for (int i = 0; i < KeyCodeMap.length; i++) {
49+
if (KeyCodeMap[i] == keycode) {
50+
return i;
51+
}
52+
}
53+
return -1;
54+
}
55+
56+
public boolean isKeyDown(int key) {
57+
if (key >= 0 && key < 16) {
58+
return keys[key];
59+
}
60+
return false;
61+
}
62+
63+
public int getLastKeyPressed() {
64+
int key = lastKeyPressed;
65+
lastKeyPressed = -1; // Reset after reading to emulate "wait for next press"
66+
return key;
67+
}
68+
}

0 commit comments

Comments
 (0)