Uploaded stuff.
parent
a0ff1cf91a
commit
383396b35c
4313
.metadata/.log
4313
.metadata/.log
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,8 @@
|
|||
*** SESSION Dec 23, 2020 07:03:49.60 -------------------------------------------
|
||||
*** SESSION Dec 25, 2020 11:04:14.20 -------------------------------------------
|
||||
*** SESSION Dec 27, 2020 18:11:45.63 -------------------------------------------
|
||||
*** SESSION Dec 28, 2020 07:25:11.73 -------------------------------------------
|
||||
*** SESSION Dec 29, 2020 08:41:22.31 -------------------------------------------
|
||||
*** SESSION Dec 29, 2020 20:45:41.12 -------------------------------------------
|
||||
*** SESSION Dec 30, 2020 07:33:14.96 -------------------------------------------
|
||||
*** SESSION Dec 31, 2020 06:46:47.09 -------------------------------------------
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21:
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31:
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0xAF:
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Registers {
|
||||
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
case 0x31:
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
public CPU() {
|
||||
|
||||
}
|
||||
|
||||
public void clock() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package playingcoffee.core.cpu;
|
||||
|
||||
public class MicroOps {
|
||||
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class MMU {
|
||||
|
||||
private int ram[];
|
||||
|
||||
public void loadBootRom() {
|
||||
byte[] data;
|
||||
try {
|
||||
data = Files.readAllBytes(Paths.get("DMG_ROM.bin"));
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
ram[i] = Byte.toUnsignedInt(data[i]);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public MMU() {
|
||||
ram = new int[0x10000];
|
||||
}
|
||||
|
||||
public void write(int value, int address) {
|
||||
ram[address] = value;
|
||||
}
|
||||
|
||||
public int read(int address) {
|
||||
return ram[address];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
// Basic CPU implementation.
|
||||
// Is subject to change.
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
default:
|
||||
new JOptionPane(String.format("Unknown opcode: 0x%2x", opcode), JOptionPane.OK_OPTION).show();;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
package playingcoffee.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.LayoutStyle.ComponentPlacement;
|
||||
|
||||
import playingcoffee.core.CPU;
|
||||
import playingcoffee.core.MMU;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JTable;
|
||||
|
||||
public class CPUDebugger {
|
||||
|
||||
private JFrame frame;
|
||||
private JTable memoryViewTable;
|
||||
|
||||
private CPU cpu;
|
||||
private MMU mmu;
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
CPUDebugger window = new CPUDebugger();
|
||||
window.frame.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CPUDebugger() {
|
||||
initialize();
|
||||
|
||||
cpu = new CPU();
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
frame = new JFrame();
|
||||
frame.setBounds(100, 100, 750, 500);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JButton btnStep = new JButton("Step");
|
||||
|
||||
JButton btnReset = new JButton("Reset");
|
||||
|
||||
JLabel lblRegisters = new JLabel("Registers:");
|
||||
|
||||
JList<String> registerList = new JList<String>();
|
||||
|
||||
memoryViewTable = new JTable();
|
||||
|
||||
JLabel lblMemoryView = new JLabel("Memory View:");
|
||||
GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
|
||||
groupLayout.setHorizontalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addComponent(btnStep)
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(btnReset))
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addComponent(lblRegisters)
|
||||
.addGap(18))
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 122, GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(18)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addComponent(lblMemoryView)
|
||||
.addComponent(memoryViewTable, GroupLayout.DEFAULT_SIZE, 574, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
groupLayout.setVerticalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(lblRegisters)
|
||||
.addComponent(lblMemoryView))
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addGap(8)
|
||||
.addComponent(memoryViewTable, GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE))
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 195, GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(18)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addComponent(btnStep)
|
||||
.addComponent(btnReset))
|
||||
.addGap(5))
|
||||
);
|
||||
frame.getContentPane().setLayout(groupLayout);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
private int cycles = 0;
|
||||
|
||||
public static final int[] INSTRUCTION_CYCLE_COUNT = {
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 20, 8, 8, 8, 4, 4, 8, 4,
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 12, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
8, 12, 12, 16, 12, 16, 8, 16, 8, 16, 12, 4, 12, 24, 8, 16,
|
||||
8, 12, 12, -1, 12, 16, 8, 16, 8, 16, 12, -1, 12, -1, 8, 16,
|
||||
12, 12, 8, -1, -1, 16, 8, 16, 16, 4, 16, -1, -1, -1, 8, 16,
|
||||
12, 12, 8, 4, -1, 16, 8, 16, 12, 8, 16, 4, -1, -1, 8, 16
|
||||
};
|
||||
|
||||
public static final int[] PREFIXED_CYCLE_COUNT = {
|
||||
8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
|
||||
};
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
if (cycles == 0) {
|
||||
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
cycles--;
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
// Apply cycle count
|
||||
cycles += INSTRUCTION_CYCLE_COUNT[opcode];
|
||||
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
cycles += INSTRUCTION_CYCLE_COUNT[opcode & 0xF];
|
||||
|
||||
switch (opcode) {
|
||||
case 0x7C:
|
||||
registers.setFlag(Registers.FLAG_Z, (registers.readH() & (1 << 7)) == 0);
|
||||
registers.setFlag(Registers.FLAG_N, false);
|
||||
registers.setFlag(Registers.FLAG_H, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final Memory memory;
|
||||
|
||||
public CPU() {
|
||||
|
||||
}
|
||||
|
||||
public void clock() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Registers {
|
||||
|
||||
private int af;
|
||||
private int bc;
|
||||
private int de;
|
||||
private int hl;
|
||||
|
||||
public int pc;
|
||||
public int sp;
|
||||
|
||||
public int readAF() {
|
||||
return af;
|
||||
}
|
||||
|
||||
public int readBC() {
|
||||
return bc;
|
||||
}
|
||||
|
||||
public int readDE() {
|
||||
return de;
|
||||
}
|
||||
|
||||
public int readHL() {
|
||||
return hl;
|
||||
}
|
||||
|
||||
public int readA() {
|
||||
return af & 0xff;
|
||||
}
|
||||
|
||||
public void writeA(int a) {
|
||||
this.af = a & 0xff;
|
||||
}
|
||||
|
||||
public int readF() {
|
||||
return (af >> 8) & 0xff;
|
||||
}
|
||||
|
||||
public void writeF(int f) {
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
public int readB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public void writeB(int b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int readC() {
|
||||
return c;
|
||||
}
|
||||
|
||||
public void writeC(int c) {
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public int readD() {
|
||||
return d;
|
||||
}
|
||||
|
||||
public void writeD(int d) {
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
public int readE() {
|
||||
return e;
|
||||
}
|
||||
|
||||
public void writeE(int e) {
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
public int readH() {
|
||||
return h;
|
||||
}
|
||||
|
||||
public void writeH(int h) {
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
public int readL() {
|
||||
return l;
|
||||
}
|
||||
|
||||
public void writeL(int l) {
|
||||
this.l = l;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Memory {
|
||||
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Registers {
|
||||
|
||||
private int a, f;
|
||||
private int b, c;
|
||||
private int d, e;
|
||||
private int h, l;
|
||||
|
||||
public int pc;
|
||||
public int sp;
|
||||
|
||||
public static final int FLAG_Z = 1 << 7;
|
||||
public static final int FLAG_N = 1 << 6;
|
||||
public static final int FLAG_H = 1 << 5;
|
||||
public static final int FLAG_C = 1 << 4;
|
||||
|
||||
public void setFlag(int flag, boolean value) {
|
||||
if (value)
|
||||
|
||||
}
|
||||
|
||||
public int readAF() {
|
||||
return a << 8 | f;
|
||||
}
|
||||
|
||||
public int readBC() {
|
||||
return b << 8 | c;
|
||||
}
|
||||
|
||||
public int readDE() {
|
||||
return d << 8 | e;
|
||||
}
|
||||
|
||||
public int readHL() {
|
||||
return h << 8 | l;
|
||||
}
|
||||
|
||||
public void writeAF(int af) {
|
||||
a = (af >> 8) & 0xFF;
|
||||
f = af & 0xFF;
|
||||
}
|
||||
|
||||
public void writeBC(int bc) {
|
||||
b = (bc >> 8) & 0xFF;
|
||||
c = bc & 0xFF;
|
||||
}
|
||||
|
||||
public void writeDE(int de) {
|
||||
d = (de >> 8) & 0xFF;
|
||||
e = de & 0xFF;
|
||||
}
|
||||
|
||||
public void writeHL(int hl) {
|
||||
h = (hl >> 8) & 0xFF;
|
||||
l = hl & 0xFF;
|
||||
}
|
||||
|
||||
public int readA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public void writeA(int a) {
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
public int readF() {
|
||||
return f;
|
||||
}
|
||||
|
||||
public void writeF(int f) {
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
public int readB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public void writeB(int b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int readC() {
|
||||
return c;
|
||||
}
|
||||
|
||||
public void writeC(int c) {
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public int readD() {
|
||||
return d;
|
||||
}
|
||||
|
||||
public void writeD(int d) {
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
public int readE() {
|
||||
return e;
|
||||
}
|
||||
|
||||
public void writeE(int e) {
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
public int readH() {
|
||||
return h;
|
||||
}
|
||||
|
||||
public void writeH(int h) {
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
public int readL() {
|
||||
return l;
|
||||
}
|
||||
|
||||
public void writeL(int l) {
|
||||
this.l = l;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() != 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
package playingcoffee.core.cpu;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import playingcoffee.core.cpu.microop.MicroOp;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
List<MicroOp> microOps;
|
||||
|
||||
public Opcode(MicroOp... ops) {
|
||||
microOps = new ArrayList<MicroOp>();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
private int cycles = 0;
|
||||
|
||||
public static int[] instructionCycle = {
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 20, 8, 8, 8, 4, 4, 8, 4,
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 12, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
8, 12, 12, 16, 12, 16, 8, 16, 8, 16, 12, 4, 12, 24, 8, 16,
|
||||
8, 12, 12, -1, 12, 16, 8, 16, 8, 16, 12, -1, 12, -1, 8, 16,
|
||||
12, 12, 8, -1, -1, 16, 8, 16, 16, 4, 16, -1, -1, -1, 8, 16,
|
||||
12, 12, 8, 4, -1, 16, 8, 16, 12, 8, 16, 4, -1, -1, 8, 16
|
||||
};
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
if (cycles == 0) {
|
||||
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
cycles--;
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
// Apply cycle count
|
||||
cycles += instructionCycle[opcode];
|
||||
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
cycles += instructionCycle[opcode];
|
||||
switch (opcode) {
|
||||
case 0x7C:
|
||||
registers.setFlag(Registers.FLAG_Z, (registers.readH() & (1 << 7)) == 0);
|
||||
registers.setFlag(Registers.FLAG_N, false);
|
||||
registers.setFlag(Registers.FLAG_H, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class MMU {
|
||||
|
||||
private int ram[];
|
||||
|
||||
|
||||
|
||||
public void write(int value, int address) {
|
||||
ram[address] = value;
|
||||
}
|
||||
|
||||
public int read(int address) {
|
||||
return ram[address];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
package playingcoffee.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.LayoutStyle.ComponentPlacement;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JTable;
|
||||
|
||||
public class CPUDebugger {
|
||||
|
||||
private JFrame frame;
|
||||
private JTable table;
|
||||
|
||||
/**
|
||||
* Launch the application.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
CPUDebugger window = new CPUDebugger();
|
||||
window.frame.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the application.
|
||||
*/
|
||||
public CPUDebugger() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the contents of the frame.
|
||||
*/
|
||||
private void initialize() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
frame = new JFrame();
|
||||
frame.setBounds(100, 100, 750, 500);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JButton btnStep = new JButton("Step");
|
||||
|
||||
JButton btnReset = new JButton("Reset");
|
||||
|
||||
JLabel lblRegisters = new JLabel("Registers:");
|
||||
|
||||
JList<String> list = new JList<String>();
|
||||
|
||||
table = new JTable();
|
||||
|
||||
JLabel lblMemoryView = new JLabel("Memory View:");
|
||||
GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
|
||||
groupLayout.setHorizontalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING, false)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addComponent(btnStep)
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(btnReset))
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addComponent(lblRegisters)
|
||||
.addGap(18))
|
||||
.addComponent(list, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGap(18)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addComponent(table, GroupLayout.DEFAULT_SIZE, 574, Short.MAX_VALUE)
|
||||
.addComponent(lblMemoryView))
|
||||
.addContainerGap())
|
||||
);
|
||||
groupLayout.setVerticalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(lblRegisters)
|
||||
.addComponent(lblMemoryView))
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(list, GroupLayout.DEFAULT_SIZE, 396, Short.MAX_VALUE)
|
||||
.addComponent(table, GroupLayout.DEFAULT_SIZE, 396, Short.MAX_VALUE))
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(btnStep)
|
||||
.addComponent(btnReset))
|
||||
.addGap(5))
|
||||
);
|
||||
frame.getContentPane().setLayout(groupLayout);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
|
||||
System.out.println(registers.readL());
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
private int cycles = 0;
|
||||
|
||||
public static int[] instructionCycle = {
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 20, 8, 8, 8, 4, 4, 8, 4,
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 12, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
8, 12, 12, 16, 12, 16, 8, 16, 8, 16, 12, 4, 12, 24, 8, 16,
|
||||
8, 12, 12, -1, 12, 16, 8, 16, 8, 16, 12, -1, 12, -1, 8, 16,
|
||||
12, 12, 8, -1, -1, 16, 8, 16, 16, 4, 16, -1, -1, -1, 8, 16,
|
||||
12, 12, 8, 4, -1, 16, 8, 16, 12, 8, 16, 4, -1, -1, 8, 16
|
||||
};
|
||||
|
||||
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
if (cycles == 0) {
|
||||
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
cycles--;
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
// Apply cycle count
|
||||
cycles += instructionCycle[opcode];
|
||||
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
cycles += instructionCycle[opcode];
|
||||
|
||||
switch (opcode) {
|
||||
case 0x7C:
|
||||
registers.setFlag(Registers.FLAG_Z, (registers.readH() & (1 << 7)) == 0);
|
||||
registers.setFlag(Registers.FLAG_N, false);
|
||||
registers.setFlag(Registers.FLAG_H, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
package playingcoffee.core.cpu;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
public Opcode(MicroOp ops...) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
package playingcoffee.core.cpu;
|
||||
|
||||
public abstract class MicroOp {
|
||||
|
||||
private int cycles;
|
||||
|
||||
public int getLength() {
|
||||
return cycles;
|
||||
}
|
||||
|
||||
public abstract void execute();
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
private int cycles = 0;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
if (cycles == 0) {
|
||||
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
cycles--;
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x7C:
|
||||
registers.setFlag(Registers.FLAG_Z, (registers.readH() & (1 << 7)) == 0);
|
||||
registers.setFlag(Registers.FLAG_N, false);
|
||||
registers.setFlag(Registers.FLAG_H, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package playingcoffee.core.cpu;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
}
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Registers {
|
||||
|
||||
private int a, f;
|
||||
private int b, c;
|
||||
private int d, e;
|
||||
private int h, l;
|
||||
|
||||
private int pc;
|
||||
private int sp;
|
||||
|
||||
public int readA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public void writeA(int a) {
|
||||
verify(a);
|
||||
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
public int readF() {
|
||||
return f;
|
||||
}
|
||||
|
||||
public void writeF(int f) {
|
||||
verify(a);
|
||||
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
public int readB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public void writeB(int b) {
|
||||
verify(a);
|
||||
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int readC() {
|
||||
return c;
|
||||
}
|
||||
|
||||
public void writeC(int c) {
|
||||
verify(a);
|
||||
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public int readD() {
|
||||
return d;
|
||||
}
|
||||
|
||||
public void writeD(int d) {
|
||||
verify(a);
|
||||
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
public int readE() {
|
||||
return e;
|
||||
}
|
||||
|
||||
public void writeE(int e) {
|
||||
verify(a);
|
||||
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
public int readH() {
|
||||
return h;
|
||||
}
|
||||
|
||||
public void writeH(int h) {
|
||||
verify(a);
|
||||
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
public int readL() {
|
||||
return l;
|
||||
}
|
||||
|
||||
public void writeL(int l) {
|
||||
verify(a);
|
||||
|
||||
this.l = l;
|
||||
}
|
||||
|
||||
public int readPC() {
|
||||
return pc;
|
||||
}
|
||||
|
||||
public void writePC(int pc) {
|
||||
verify(a);
|
||||
|
||||
this.pc = pc;
|
||||
}
|
||||
|
||||
public int readSP() {
|
||||
return sp;
|
||||
}
|
||||
|
||||
public void writeSP(int sp) {
|
||||
verify(a);
|
||||
|
||||
this.sp = sp;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
package playingcoffee.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.LayoutStyle.ComponentPlacement;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
|
||||
import playingcoffee.core.CPU;
|
||||
import playingcoffee.core.MMU;
|
||||
|
||||
public class CPUDebugger {
|
||||
|
||||
private JFrame frmCpuDebugger;
|
||||
private JList<String> registerList;
|
||||
|
||||
private MMU mmu;
|
||||
private CPU cpu;
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
CPUDebugger window = new CPUDebugger();
|
||||
window.frmCpuDebugger.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CPUDebugger() {
|
||||
initialize();
|
||||
|
||||
mmu = new MMU();
|
||||
cpu = new CPU(mmu);
|
||||
|
||||
updateValues();
|
||||
}
|
||||
|
||||
private void updateValues() {
|
||||
DefaultListModel<String> model = new DefaultListModel<String>();
|
||||
model.addElement("AF: 0x" + Integer.toHexString(cpu.getRegisters().readAF()));
|
||||
model.addElement("BC: 0x" + Integer.toHexString(cpu.getRegisters().readBC()));
|
||||
model.addElement("DE: 0x" + Integer.toHexString(cpu.getRegisters().readDE()));
|
||||
model.addElement("HL: 0x" + Integer.toHexString(cpu.getRegisters().readHL()));
|
||||
model.addElement("PC: 0x" + Integer.toHexString(cpu.getRegisters().readPC()));
|
||||
model.addElement("SP: 0x" + Integer.toHexString(cpu.getRegisters().readSP()));
|
||||
|
||||
registerList.setModel(model);
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
frmCpuDebugger = new JFrame();
|
||||
frmCpuDebugger.setTitle("CPU Debugger");
|
||||
frmCpuDebugger.setBounds(100, 100, 350, 350);
|
||||
frmCpuDebugger.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JButton btnStep = new JButton("Step");
|
||||
btnStep.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
cpu.cycle();
|
||||
updateValues();
|
||||
}
|
||||
});
|
||||
|
||||
JButton btnReset = new JButton("Reset");
|
||||
|
||||
JLabel lblRegisters = new JLabel("Registers:");
|
||||
|
||||
registerList = new JList<String>();
|
||||
GroupLayout groupLayout = new GroupLayout(frmCpuDebugger.getContentPane());
|
||||
groupLayout.setHorizontalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addComponent(registerList, GroupLayout.DEFAULT_SIZE, 314, Short.MAX_VALUE)
|
||||
.addComponent(lblRegisters)
|
||||
.addGroup(Alignment.TRAILING, groupLayout.createSequentialGroup()
|
||||
.addComponent(btnStep)
|
||||
.addPreferredGap(ComponentPlacement.RELATED, 198, Short.MAX_VALUE)
|
||||
.addComponent(btnReset)))
|
||||
.addContainerGap())
|
||||
);
|
||||
groupLayout.setVerticalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(lblRegisters)
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 195, GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(51)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(btnReset)
|
||||
.addComponent(btnStep))
|
||||
.addContainerGap())
|
||||
);
|
||||
frmCpuDebugger.getContentPane().setLayout(groupLayout);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
package playingcoffee.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.LayoutStyle.ComponentPlacement;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
|
||||
import playingcoffee.core.CPU;
|
||||
import playingcoffee.core.MMU;
|
||||
|
||||
public class CPUDebugger {
|
||||
|
||||
private JFrame frame;
|
||||
private JTable memoryViewTable;
|
||||
private JList<String> registerList;
|
||||
|
||||
private MMU mmu;
|
||||
private CPU cpu;
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
CPUDebugger window = new CPUDebugger();
|
||||
window.frame.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CPUDebugger() {
|
||||
initialize();
|
||||
|
||||
mmu = new MMU();
|
||||
cpu = new CPU();
|
||||
|
||||
updateValues();
|
||||
}
|
||||
|
||||
private void updateValues() {
|
||||
DefaultListModel<String> model = new DefaultListModel<String>();
|
||||
model.
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
frame = new JFrame();
|
||||
frame.setBounds(100, 100, 750, 500);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JButton btnStep = new JButton("Step");
|
||||
|
||||
JButton btnReset = new JButton("Reset");
|
||||
|
||||
JLabel lblRegisters = new JLabel("Registers:");
|
||||
|
||||
registerList = new JList<String>();
|
||||
|
||||
memoryViewTable = new JTable();
|
||||
|
||||
JLabel lblMemoryView = new JLabel("Memory View:");
|
||||
GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
|
||||
groupLayout.setHorizontalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addComponent(btnStep)
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(btnReset))
|
||||
.addComponent(lblRegisters)
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 122, GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(18)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addComponent(lblMemoryView)
|
||||
.addComponent(memoryViewTable, GroupLayout.DEFAULT_SIZE, 574, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
groupLayout.setVerticalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(lblRegisters)
|
||||
.addComponent(lblMemoryView))
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addGap(8)
|
||||
.addComponent(memoryViewTable, GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE))
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 195, GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(18)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addComponent(btnStep)
|
||||
.addComponent(btnReset))
|
||||
.addGap(5))
|
||||
);
|
||||
frame.getContentPane().setLayout(groupLayout);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Registers {
|
||||
|
||||
private int a, f;
|
||||
private int b, c;
|
||||
private int d, e;
|
||||
private int h, l;
|
||||
|
||||
private int pc;
|
||||
private int sp;
|
||||
|
||||
public int readA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public void writeA(int a) {
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
public int readF() {
|
||||
return f;
|
||||
}
|
||||
|
||||
public void writeF(int f) {
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
public int readB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public void writeB(int b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int readC() {
|
||||
return c;
|
||||
}
|
||||
|
||||
public void writeC(int c) {
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public int readD() {
|
||||
return d;
|
||||
}
|
||||
|
||||
public void writeD(int d) {
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
public int readE() {
|
||||
return e;
|
||||
}
|
||||
|
||||
public void writeE(int e) {
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
public int readH() {
|
||||
return h;
|
||||
}
|
||||
|
||||
public void writeH(int h) {
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
public int readL() {
|
||||
return l;
|
||||
}
|
||||
|
||||
public void writeL(int l) {
|
||||
this.l = l;
|
||||
}
|
||||
|
||||
public int readPC() {
|
||||
return pc;
|
||||
}
|
||||
|
||||
public void writePC(int pc) {
|
||||
this.pc = pc;
|
||||
}
|
||||
|
||||
public int readSP() {
|
||||
return sp;
|
||||
}
|
||||
|
||||
public void writeSP(int sp) {
|
||||
this.sp = sp;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Gameboy {
|
||||
|
||||
private CPU m_CPU;
|
||||
|
||||
public Gameboy() {
|
||||
m_CPU = new CPU();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
private int cycles = 0;
|
||||
|
||||
public static int[] instructionCycle = {
|
||||
|
||||
};
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
if (cycles == 0) {
|
||||
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
cycles--;
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
// Apply cycle count
|
||||
|
||||
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x7C:
|
||||
registers.setFlag(Registers.FLAG_Z, (registers.readH() & (1 << 7)) == 0);
|
||||
registers.setFlag(Registers.FLAG_N, false);
|
||||
registers.setFlag(Registers.FLAG_H, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Registers {
|
||||
|
||||
private int a, f;
|
||||
private int b, c;
|
||||
private int d, e;
|
||||
private int h, l;
|
||||
|
||||
private int pc;
|
||||
private int sp;
|
||||
|
||||
public int readA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public void writeA(int a) {
|
||||
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
public int readF() {
|
||||
return f;
|
||||
}
|
||||
|
||||
public void writeF(int f) {
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
public int readB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public void writeB(int b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int readC() {
|
||||
return c;
|
||||
}
|
||||
|
||||
public void writeC(int c) {
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public int readD() {
|
||||
return d;
|
||||
}
|
||||
|
||||
public void writeD(int d) {
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
public int readE() {
|
||||
return e;
|
||||
}
|
||||
|
||||
public void writeE(int e) {
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
public int readH() {
|
||||
return h;
|
||||
}
|
||||
|
||||
public void writeH(int h) {
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
public int readL() {
|
||||
return l;
|
||||
}
|
||||
|
||||
public void writeL(int l) {
|
||||
this.l = l;
|
||||
}
|
||||
|
||||
public int readPC() {
|
||||
return pc;
|
||||
}
|
||||
|
||||
public void writePC(int pc) {
|
||||
this.pc = pc;
|
||||
}
|
||||
|
||||
public int readSP() {
|
||||
return sp;
|
||||
}
|
||||
|
||||
public void writeSP(int sp) {
|
||||
this.sp = sp;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package playingcoffee.core.cpu;
|
||||
|
||||
import playingcoffee.core.cpu.microop.MicroOp;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
MicroOp microOps[];
|
||||
|
||||
public Opcode(MicroOp... ops) {
|
||||
microOps = ops;
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
for(MicroOp op : microOps)
|
||||
op.execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.readPC());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
private Op[] ops;
|
||||
|
||||
public Opcode(Op... ops) {
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
for (Op op : ops)
|
||||
op.execute(regs, mmu);
|
||||
}
|
||||
|
||||
public interface Op {
|
||||
|
||||
public void execute(Registers regs, MMU mmu);
|
||||
|
||||
}
|
||||
|
||||
public class Read16BitOperand implements Op {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
package playingcoffee.core.cpu;
|
||||
|
||||
import playingcoffee.core.Memory;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final Memory memory;
|
||||
|
||||
public CPU(Memory memory) {
|
||||
this.memory = memory;
|
||||
}
|
||||
|
||||
public void registerOpcodes() {
|
||||
// Example: instructions[0x01] = new OpcodeBuilder().read(OpcodeArgument.C, OpcodeArgument.PC_INC).read(OpcodeArgument.B, OpcodeArgument.PC_INC);
|
||||
|
||||
}
|
||||
|
||||
public void clock() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
private Op[] ops;
|
||||
|
||||
public Opcode(Op... ops) {
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
for (Op op : ops)
|
||||
op.execute();
|
||||
}
|
||||
|
||||
public class Op {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package playingcoffee.core.cpu;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import playingcoffee.core.cpu.microop.MicroOp;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
List<MicroOp> microOps;
|
||||
|
||||
public Opcode(MicroOp... ops) {
|
||||
microOps = new ArrayList<MicroOp>();
|
||||
microOps.add(ops);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
package playingcoffee.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.LayoutStyle.ComponentPlacement;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
|
||||
import playingcoffee.core.CPU;
|
||||
import playingcoffee.core.MMU;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
public class CPUDebugger {
|
||||
|
||||
private JFrame frmCpuDebugger;
|
||||
private JList<String> registerList;
|
||||
|
||||
private MMU mmu;
|
||||
private CPU cpu;
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
CPUDebugger window = new CPUDebugger();
|
||||
window.frmCpuDebugger.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CPUDebugger() {
|
||||
initialize();
|
||||
|
||||
mmu = new MMU();
|
||||
cpu = new CPU(mmu);
|
||||
|
||||
updateValues();
|
||||
}
|
||||
|
||||
private void updateValues() {
|
||||
DefaultListModel<String> model = new DefaultListModel<String>();
|
||||
model.addElement("AF: 0x" + Integer.toHexString(cpu.getRegisters().readAF()));
|
||||
model.addElement("BC: 0x" + Integer.toHexString(cpu.getRegisters().readBC()));
|
||||
model.addElement("DE: 0x" + Integer.toHexString(cpu.getRegisters().readDE()));
|
||||
model.addElement("HL: 0x" + Integer.toHexString(cpu.getRegisters().readHL()));
|
||||
model.addElement("PC: 0x" + Integer.toHexString(cpu.getRegisters().readPC()));
|
||||
model.addElement("SP: 0x" + Integer.toHexString(cpu.getRegisters().readSP()));
|
||||
|
||||
registerList.setModel(model);
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
frmCpuDebugger = new JFrame();
|
||||
frmCpuDebugger.setTitle("CPU Debugger");
|
||||
frmCpuDebugger.setBounds(100, 100, 350, 350);
|
||||
frmCpuDebugger.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JButton btnStep = new JButton("Step");
|
||||
btnStep.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
JButton btnReset = new JButton("Reset");
|
||||
|
||||
JLabel lblRegisters = new JLabel("Registers:");
|
||||
|
||||
registerList = new JList<String>();
|
||||
GroupLayout groupLayout = new GroupLayout(frmCpuDebugger.getContentPane());
|
||||
groupLayout.setHorizontalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addComponent(registerList, GroupLayout.DEFAULT_SIZE, 314, Short.MAX_VALUE)
|
||||
.addComponent(lblRegisters)
|
||||
.addGroup(Alignment.TRAILING, groupLayout.createSequentialGroup()
|
||||
.addComponent(btnStep)
|
||||
.addPreferredGap(ComponentPlacement.RELATED, 198, Short.MAX_VALUE)
|
||||
.addComponent(btnReset)))
|
||||
.addContainerGap())
|
||||
);
|
||||
groupLayout.setVerticalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(lblRegisters)
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 195, GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(51)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(btnReset)
|
||||
.addComponent(btnStep))
|
||||
.addContainerGap())
|
||||
);
|
||||
frmCpuDebugger.getContentPane().setLayout(groupLayout);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
package playingcoffee.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.LayoutStyle.ComponentPlacement;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JTable;
|
||||
|
||||
public class CPUDebugger {
|
||||
|
||||
private JFrame frame;
|
||||
private JTable table;
|
||||
|
||||
/**
|
||||
* Launch the application.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
CPUDebugger window = new CPUDebugger();
|
||||
window.frame.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CPUDebugger() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
frame = new JFrame();
|
||||
frame.setBounds(100, 100, 750, 500);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JButton btnStep = new JButton("Step");
|
||||
|
||||
JButton btnReset = new JButton("Reset");
|
||||
|
||||
JLabel lblRegisters = new JLabel("Registers:");
|
||||
|
||||
JList<String> list = new JList<String>();
|
||||
|
||||
table = new JTable();
|
||||
|
||||
JLabel lblMemoryView = new JLabel("Memory View:");
|
||||
GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
|
||||
groupLayout.setHorizontalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addComponent(btnStep)
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(btnReset))
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addComponent(lblRegisters)
|
||||
.addGap(18))
|
||||
.addComponent(list, GroupLayout.PREFERRED_SIZE, 122, GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(18)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addComponent(lblMemoryView)
|
||||
.addComponent(table, GroupLayout.DEFAULT_SIZE, 574, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
groupLayout.setVerticalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(lblRegisters)
|
||||
.addComponent(lblMemoryView))
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addGap(8)
|
||||
.addComponent(table, GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE))
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(list, GroupLayout.PREFERRED_SIZE, 195, GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(18)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addComponent(btnStep)
|
||||
.addComponent(btnReset))
|
||||
.addGap(5))
|
||||
);
|
||||
frame.getContentPane().setLayout(groupLayout);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
// Basic CPU implementation.
|
||||
// Is subject to change.
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
default:
|
||||
JOptionPane.showMessageDialog(null, String.format("Unknown opcode: 0x%2x", opcode));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Registers {
|
||||
|
||||
private int a, f;
|
||||
private int b, c;
|
||||
private int d, e;
|
||||
private int h, l;
|
||||
|
||||
public int pc;
|
||||
public int sp;
|
||||
|
||||
public static final int FLAG_Z = 1 << 7;
|
||||
|
||||
public void setFlag(int flag, boolean value) {
|
||||
|
||||
}
|
||||
|
||||
public int readAF() {
|
||||
return a << 8 | f;
|
||||
}
|
||||
|
||||
public int readBC() {
|
||||
return b << 8 | c;
|
||||
}
|
||||
|
||||
public int readDE() {
|
||||
return d << 8 | e;
|
||||
}
|
||||
|
||||
public int readHL() {
|
||||
return h << 8 | l;
|
||||
}
|
||||
|
||||
public void writeAF(int af) {
|
||||
a = (af >> 8) & 0xFF;
|
||||
f = af & 0xFF;
|
||||
}
|
||||
|
||||
public void writeBC(int bc) {
|
||||
b = (bc >> 8) & 0xFF;
|
||||
c = bc & 0xFF;
|
||||
}
|
||||
|
||||
public void writeDE(int de) {
|
||||
d = (de >> 8) & 0xFF;
|
||||
e = de & 0xFF;
|
||||
}
|
||||
|
||||
public void writeHL(int hl) {
|
||||
h = (hl >> 8) & 0xFF;
|
||||
l = hl & 0xFF;
|
||||
}
|
||||
|
||||
public int readA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public void writeA(int a) {
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
public int readF() {
|
||||
return f;
|
||||
}
|
||||
|
||||
public void writeF(int f) {
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
public int readB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public void writeB(int b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int readC() {
|
||||
return c;
|
||||
}
|
||||
|
||||
public void writeC(int c) {
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public int readD() {
|
||||
return d;
|
||||
}
|
||||
|
||||
public void writeD(int d) {
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
public int readE() {
|
||||
return e;
|
||||
}
|
||||
|
||||
public void writeE(int e) {
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
public int readH() {
|
||||
return h;
|
||||
}
|
||||
|
||||
public void writeH(int h) {
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
public int readL() {
|
||||
return l;
|
||||
}
|
||||
|
||||
public void writeL(int l) {
|
||||
this.l = l;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
private Op[] ops;
|
||||
|
||||
private final Registers registers;
|
||||
private final MMU mmu;
|
||||
|
||||
private int stored;
|
||||
|
||||
public Opcode(Registers registers, MMU mmu, Op... ops) {
|
||||
this.registers = registers;
|
||||
this.mmu = mmu;
|
||||
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
for (Op op : ops)
|
||||
op.execute();
|
||||
}
|
||||
|
||||
public interface Op {
|
||||
|
||||
public void execute();
|
||||
|
||||
}
|
||||
|
||||
public class Read16BitOperand implements Op {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
stored = (mmu.read(registers.pc++) << 8) | mmu.read(registers.pc);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
package playingcoffee.core.cpu;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import playingcoffee.core.cpu.microop.MicroOp;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
List<MicroOp> microOps;
|
||||
|
||||
public Opcode(MicroOp... ops) {
|
||||
microOps = new ArrayList<MicroOp>(ops);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Registers {
|
||||
|
||||
private int a, f;
|
||||
private int b, c;
|
||||
private int d, e;
|
||||
private int h, l;
|
||||
|
||||
public int pc;
|
||||
public int sp;
|
||||
|
||||
public static final int FLAG_Z = 1 << 7;
|
||||
public static final int FLAG_N = 1 << 6;
|
||||
public static final int FLAG_H = 1 << 5;
|
||||
public static final int FLAG_C = 1 << 4;
|
||||
|
||||
public void setFlag(int flag, boolean value) {
|
||||
if (value)
|
||||
f |= flag;
|
||||
}
|
||||
|
||||
public int readAF() {
|
||||
return a << 8 | f;
|
||||
}
|
||||
|
||||
public int readBC() {
|
||||
return b << 8 | c;
|
||||
}
|
||||
|
||||
public int readDE() {
|
||||
return d << 8 | e;
|
||||
}
|
||||
|
||||
public int readHL() {
|
||||
return h << 8 | l;
|
||||
}
|
||||
|
||||
public void writeAF(int af) {
|
||||
a = (af >> 8) & 0xFF;
|
||||
f = af & 0xFF;
|
||||
}
|
||||
|
||||
public void writeBC(int bc) {
|
||||
b = (bc >> 8) & 0xFF;
|
||||
c = bc & 0xFF;
|
||||
}
|
||||
|
||||
public void writeDE(int de) {
|
||||
d = (de >> 8) & 0xFF;
|
||||
e = de & 0xFF;
|
||||
}
|
||||
|
||||
public void writeHL(int hl) {
|
||||
h = (hl >> 8) & 0xFF;
|
||||
l = hl & 0xFF;
|
||||
}
|
||||
|
||||
public int readA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public void writeA(int a) {
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
public int readF() {
|
||||
return f;
|
||||
}
|
||||
|
||||
public void writeF(int f) {
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
public int readB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public void writeB(int b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int readC() {
|
||||
return c;
|
||||
}
|
||||
|
||||
public void writeC(int c) {
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public int readD() {
|
||||
return d;
|
||||
}
|
||||
|
||||
public void writeD(int d) {
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
public int readE() {
|
||||
return e;
|
||||
}
|
||||
|
||||
public void writeE(int e) {
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
public int readH() {
|
||||
return h;
|
||||
}
|
||||
|
||||
public void writeH(int h) {
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
public int readL() {
|
||||
return l;
|
||||
}
|
||||
|
||||
public void writeL(int l) {
|
||||
this.l = l;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Op {
|
||||
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x7C:
|
||||
registers.setFlag(Registers.FLAG_Z, (registers.readH() & (1 << 7)) == 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%fx\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
package playingcoffee.core.cpu;
|
||||
|
||||
import playingcoffee.core.Memory;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final Memory memory;
|
||||
|
||||
public CPU(Memory memory) {
|
||||
this.memory = memory;
|
||||
}
|
||||
|
||||
public void registerOpcodes() {
|
||||
// Example: instructions[0x01] = new OpcodeBuilder().read(OpcodeArgument.C, OpcodeArgument.PC_INC).read(OpcodeArgument.B, OpcodeArgument.PC_INC);
|
||||
}
|
||||
|
||||
public void clock() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
private Op[] ops;
|
||||
|
||||
public Opcode(Op... ops) {
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
for (Op op : ops)
|
||||
op.execute(regs, mmu);
|
||||
}
|
||||
|
||||
public interface Op {
|
||||
|
||||
public void execute(Registers regs, MMU mmu);
|
||||
|
||||
}
|
||||
|
||||
public class Read16BitOperand implements Op {
|
||||
|
||||
@Override
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
private Op[] ops;
|
||||
|
||||
public Opcode(Op... ops) {
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
for (Op op : ops)
|
||||
op.execute(regs, mmu);
|
||||
}
|
||||
|
||||
public interface Op {
|
||||
|
||||
public void execute(Registers regs, MMU mmu);
|
||||
|
||||
}
|
||||
|
||||
public class Read16BitOp implements {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Gameboy {
|
||||
|
||||
private CPU m_CPU;
|
||||
|
||||
public Gameboy() {
|
||||
m_CPU = new CPU();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
// Basic CPU implementation.
|
||||
// Is subject to change.
|
||||
switch (opcode) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
private int cycles = 0;
|
||||
|
||||
public static int[] instructionCycle = {
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 20, 8, 8, 8, 4, 4, 8, 4,
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 12, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
8, 12, 12, 16, 12, 16, 8, 16, 8, 16, 12, 4, 12, 24, 8, 16,
|
||||
8, 12, 12, -1, 12, 16, 8, 16, 8, 16, 12, -1, 12, -1, 8, 16
|
||||
};
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
if (cycles == 0) {
|
||||
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
cycles--;
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
// Apply cycle count
|
||||
|
||||
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x7C:
|
||||
registers.setFlag(Registers.FLAG_Z, (registers.readH() & (1 << 7)) == 0);
|
||||
registers.setFlag(Registers.FLAG_N, false);
|
||||
registers.setFlag(Registers.FLAG_H, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Gameboy {
|
||||
|
||||
private CPU m_CPU;
|
||||
|
||||
public Gameboy() {
|
||||
m_CPU = new CPU();
|
||||
|
||||
while (true) {
|
||||
m_CPU.clock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package playingcoffee.core.cpu;
|
||||
|
||||
public abstract class MicroOp {
|
||||
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
package playingcoffee.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.LayoutStyle.ComponentPlacement;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
|
||||
import playingcoffee.core.CPU;
|
||||
import playingcoffee.core.MMU;
|
||||
|
||||
public class CPUDebugger {
|
||||
|
||||
private JFrame frame;
|
||||
private JTable memoryViewTable;
|
||||
private JList<String> registerList;
|
||||
|
||||
private MMU mmu;
|
||||
private CPU cpu;
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
CPUDebugger window = new CPUDebugger();
|
||||
window.frame.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CPUDebugger() {
|
||||
initialize();
|
||||
|
||||
mmu = new MMU();
|
||||
cpu = new CPU();
|
||||
|
||||
updateValues();
|
||||
}
|
||||
|
||||
private void updateValues() {
|
||||
DefaultListModel<String> model = new DefaultListModel<String>();
|
||||
model.addElement("");
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
frame = new JFrame();
|
||||
frame.setBounds(100, 100, 750, 500);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JButton btnStep = new JButton("Step");
|
||||
|
||||
JButton btnReset = new JButton("Reset");
|
||||
|
||||
JLabel lblRegisters = new JLabel("Registers:");
|
||||
|
||||
registerList = new JList<String>();
|
||||
|
||||
memoryViewTable = new JTable();
|
||||
|
||||
JLabel lblMemoryView = new JLabel("Memory View:");
|
||||
GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
|
||||
groupLayout.setHorizontalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addComponent(btnStep)
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(btnReset))
|
||||
.addComponent(lblRegisters)
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 122, GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(18)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addComponent(lblMemoryView)
|
||||
.addComponent(memoryViewTable, GroupLayout.DEFAULT_SIZE, 574, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
groupLayout.setVerticalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(lblRegisters)
|
||||
.addComponent(lblMemoryView))
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addGap(8)
|
||||
.addComponent(memoryViewTable, GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE))
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 195, GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(18)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addComponent(btnStep)
|
||||
.addComponent(btnReset))
|
||||
.addGap(5))
|
||||
);
|
||||
frame.getContentPane().setLayout(groupLayout);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
import playingcoffee.core.Memory;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final Memory memory;
|
||||
|
||||
public CPU(Memory memory) {
|
||||
this.memory = memory;
|
||||
}
|
||||
|
||||
public void clock() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
// Basic CPU implementation.
|
||||
// Is subject to change.
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
default:
|
||||
new JOptionPane(String.format("Unknown opcode: 0x%2x", opcode), JOptionPane.OK_OPTION);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.readPC());
|
||||
registers.writePC(registers.readPC() + 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
private Op[] ops;
|
||||
|
||||
private final Registers registers;
|
||||
private final MMU mmu;
|
||||
|
||||
private int stored;
|
||||
|
||||
public Opcode(Registers registers, MMU mmu, Op... ops) {
|
||||
this.registers = registers;
|
||||
this.mmu = mmu;
|
||||
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
for (Op op : ops)
|
||||
op.execute(this);
|
||||
}
|
||||
|
||||
public interface Op {
|
||||
|
||||
public void execute(Opcode opcode);
|
||||
|
||||
}
|
||||
|
||||
public class Read16BitOperand implements Op {
|
||||
|
||||
@Override
|
||||
public void execute(Opcode opcode) {
|
||||
opcode.stored =
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
private Op[] ops;
|
||||
|
||||
private final Registers registers;
|
||||
private final MMU mmu;
|
||||
|
||||
public Opcode(Registers registers, MMU mmu, Op... ops) {
|
||||
this.registers = registers;
|
||||
this.mmu = mmu;
|
||||
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
for (Op op : ops)
|
||||
op.execute(regs, mmu);
|
||||
}
|
||||
|
||||
public interface Op {
|
||||
|
||||
public void execute(Opcode opcode);
|
||||
|
||||
}
|
||||
|
||||
public class Read16BitOperand implements Op {
|
||||
|
||||
@Override
|
||||
public void execute(Opcode opcode) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
private Op[] ops;
|
||||
|
||||
public Opcode(Op... ops) {
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
for (Op op : ops)
|
||||
op.execute(regs, mmu);
|
||||
}
|
||||
|
||||
public interface Op {
|
||||
|
||||
public void execute(Registers regs, MMU mmu);
|
||||
|
||||
}
|
||||
|
||||
public class Read16BitOperand implements Op {
|
||||
|
||||
@Override
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Registers {
|
||||
|
||||
private int a, f;
|
||||
private int b, c;
|
||||
private int d, e;
|
||||
private int h, l;
|
||||
|
||||
private int pc;
|
||||
private int sp;
|
||||
|
||||
public int readA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public void writeA(int a) {
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
public int readF() {
|
||||
return f;
|
||||
}
|
||||
|
||||
public void writeF(int f) {
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
public int readB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public void writeB(int b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int readC() {
|
||||
return c;
|
||||
}
|
||||
|
||||
public void writeC(int c) {
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public int readD() {
|
||||
return d;
|
||||
}
|
||||
|
||||
public void writeD(int d) {
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
public int readE() {
|
||||
return e;
|
||||
}
|
||||
|
||||
public void writeE(int e) {
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
public int readH() {
|
||||
return h;
|
||||
}
|
||||
|
||||
public void writeH(int h) {
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
public int readL() {
|
||||
return l;
|
||||
}
|
||||
|
||||
public void writeL(int l) {
|
||||
this.l = l;
|
||||
}
|
||||
|
||||
public int readPC() {
|
||||
return pc;
|
||||
}
|
||||
|
||||
public void writePC(int pc) {
|
||||
this.pc = pc;
|
||||
}
|
||||
|
||||
public int readSP() {
|
||||
return sp;
|
||||
}
|
||||
|
||||
public void writeSP(int sp) {
|
||||
this.sp = sp;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Registers {
|
||||
|
||||
private int a, f;
|
||||
private int b, c;
|
||||
private int d, e;
|
||||
private int h, l;
|
||||
|
||||
private int pc;
|
||||
private int sp;
|
||||
|
||||
public int readAF() {
|
||||
return a << 8 | F;
|
||||
}
|
||||
|
||||
public int readA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public void writeA(int a) {
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
public int readF() {
|
||||
return f;
|
||||
}
|
||||
|
||||
public void writeF(int f) {
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
public int readB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public void writeB(int b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int readC() {
|
||||
return c;
|
||||
}
|
||||
|
||||
public void writeC(int c) {
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public int readD() {
|
||||
return d;
|
||||
}
|
||||
|
||||
public void writeD(int d) {
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
public int readE() {
|
||||
return e;
|
||||
}
|
||||
|
||||
public void writeE(int e) {
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
public int readH() {
|
||||
return h;
|
||||
}
|
||||
|
||||
public void writeH(int h) {
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
public int readL() {
|
||||
return l;
|
||||
}
|
||||
|
||||
public void writeL(int l) {
|
||||
this.l = l;
|
||||
}
|
||||
|
||||
public int readPC() {
|
||||
return pc;
|
||||
}
|
||||
|
||||
public void writePC(int pc) {
|
||||
this.pc = pc;
|
||||
}
|
||||
|
||||
public int readSP() {
|
||||
return sp;
|
||||
}
|
||||
|
||||
public void writeSP(int sp) {
|
||||
this.sp = sp;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x7C:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
private Op[] ops;
|
||||
|
||||
private final Registers registers;
|
||||
private final MMU mmu;
|
||||
|
||||
public Opcode(Registers registers, MMU mmu, Op... ops) {
|
||||
this.registers = registers;
|
||||
this.mmu = mmu;
|
||||
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
for (Op op : ops)
|
||||
op.execute(regs, mmu);
|
||||
}
|
||||
|
||||
public interface Op {
|
||||
|
||||
public void execute(Registers regs, MMU mmu);
|
||||
|
||||
}
|
||||
|
||||
public class Read16BitOperand implements Op {
|
||||
|
||||
@Override
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final Memory memory;
|
||||
|
||||
public CPU(Memory memory) {
|
||||
this.memory = memory;
|
||||
}
|
||||
|
||||
public void clock() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
private Op[] ops;
|
||||
|
||||
private final Registers registers;
|
||||
private final MMU mmu;
|
||||
|
||||
private int stored;
|
||||
|
||||
public Opcode(Registers registers, MMU mmu, Op... ops) {
|
||||
this.registers = registers;
|
||||
this.mmu = mmu;
|
||||
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
for (Op op : ops)
|
||||
op.execute();
|
||||
}
|
||||
|
||||
public interface Op {
|
||||
|
||||
public void execute();
|
||||
|
||||
}
|
||||
|
||||
public class Read16BitOperand implements Op {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
stored = (mmu.read(registers.pc++) << 8) | mmu.read(registers.pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32:
|
||||
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
private int cycles = 0;
|
||||
|
||||
public static int[] instructionCycle = {
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 20, 8, 8, 8, 4, 4, 8, 4,
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 12, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
8, 12, 12, 16, 12, 16, 8, 16, 8, 16, 12, 4, 12, 24, 8, 16,
|
||||
|
||||
};
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
if (cycles == 0) {
|
||||
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
cycles--;
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
// Apply cycle count
|
||||
|
||||
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x7C:
|
||||
registers.setFlag(Registers.FLAG_Z, (registers.readH() & (1 << 7)) == 0);
|
||||
registers.setFlag(Registers.FLAG_N, false);
|
||||
registers.setFlag(Registers.FLAG_H, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class MMU {
|
||||
|
||||
private int ram[];
|
||||
|
||||
public void write(int value, int address) {
|
||||
ram[address] = value;
|
||||
}
|
||||
|
||||
public int read(int address) {
|
||||
return ram[address];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
package playingcoffee.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
public class CPUDebugger {
|
||||
|
||||
private JFrame frame;
|
||||
|
||||
/**
|
||||
* Launch the application.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
CPUDebugger window = new CPUDebugger();
|
||||
window.frame.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the application.
|
||||
*/
|
||||
public CPUDebugger() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the contents of the frame.
|
||||
*/
|
||||
private void initialize() {
|
||||
frame = new JFrame();
|
||||
frame.setBounds(100, 100, 450, 300);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
package playingcoffee.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.LayoutStyle.ComponentPlacement;
|
||||
|
||||
import playingcoffee.core.CPU;
|
||||
import playingcoffee.core.MMU;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JTable;
|
||||
|
||||
public class CPUDebugger {
|
||||
|
||||
private JFrame frame;
|
||||
private JTable memoryViewTable;
|
||||
|
||||
private CPU cpu;
|
||||
private MMU mmu;
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
CPUDebugger window = new CPUDebugger();
|
||||
window.frame.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CPUDebugger() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
frame = new JFrame();
|
||||
frame.setBounds(100, 100, 750, 500);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JButton btnStep = new JButton("Step");
|
||||
|
||||
JButton btnReset = new JButton("Reset");
|
||||
|
||||
JLabel lblRegisters = new JLabel("Registers:");
|
||||
|
||||
JList<String> registerList = new JList<String>();
|
||||
|
||||
memoryViewTable = new JTable();
|
||||
|
||||
JLabel lblMemoryView = new JLabel("Memory View:");
|
||||
GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
|
||||
groupLayout.setHorizontalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addComponent(btnStep)
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(btnReset))
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addComponent(lblRegisters)
|
||||
.addGap(18))
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 122, GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(18)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addComponent(lblMemoryView)
|
||||
.addComponent(memoryViewTable, GroupLayout.DEFAULT_SIZE, 574, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
groupLayout.setVerticalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(lblRegisters)
|
||||
.addComponent(lblMemoryView))
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addGap(8)
|
||||
.addComponent(memoryViewTable, GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE))
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 195, GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(18)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addComponent(btnStep)
|
||||
.addComponent(btnReset))
|
||||
.addGap(5))
|
||||
);
|
||||
frame.getContentPane().setLayout(groupLayout);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
case 0x31:
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
private Op[] ops;
|
||||
|
||||
private final Registers registers;
|
||||
private final MMU mmu;
|
||||
|
||||
public Opcode(Registers registers, MMU mmu, Op... ops) {
|
||||
this.registers = registers;
|
||||
this.mmu = mmu;
|
||||
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
for (Op op : ops)
|
||||
op.execute(this);
|
||||
}
|
||||
|
||||
public interface Op {
|
||||
|
||||
public void execute(Opcode opcode);
|
||||
|
||||
}
|
||||
|
||||
public class Read16BitOperand implements Op {
|
||||
|
||||
@Override
|
||||
public void execute(Opcode opcode) {
|
||||
opcode.registers.pc = 0x00;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x7C:
|
||||
break;
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
private Op[] ops;
|
||||
|
||||
private final Registers registers;
|
||||
private final MMU mmu;
|
||||
|
||||
private int operand;
|
||||
|
||||
public Opcode(Registers registers, MMU mmu, Op... ops) {
|
||||
this.registers = registers;
|
||||
this.mmu = mmu;
|
||||
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
for (Op op : ops)
|
||||
op.execute();
|
||||
}
|
||||
|
||||
public interface Op {
|
||||
|
||||
public void execute();
|
||||
|
||||
}
|
||||
|
||||
public class Read16BitOperand implements Op {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
operand = (mmu.read(registers.pc++) << 8) | mmu.read(registers.pc);
|
||||
}
|
||||
}
|
||||
|
||||
public class
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
private int cycles = 0;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
if (cycles == 0) {
|
||||
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x7C:
|
||||
registers.setFlag(Registers.FLAG_Z, (registers.readH() & (1 << 7)) == 0);
|
||||
registers.setFlag(Registers.FLAG_N, false);
|
||||
registers.setFlag(Registers.FLAG_H, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
package playingcoffee.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.LayoutStyle.ComponentPlacement;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
|
||||
import playingcoffee.core.CPU;
|
||||
import playingcoffee.core.MMU;
|
||||
|
||||
public class CPUDebugger {
|
||||
|
||||
private JFrame frmCpuDebugger;
|
||||
private JList<String> registerList;
|
||||
|
||||
private MMU mmu;
|
||||
private CPU cpu;
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
CPUDebugger window = new CPUDebugger();
|
||||
window.frmCpuDebugger.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CPUDebugger() {
|
||||
initialize();
|
||||
|
||||
mmu = new MMU();
|
||||
cpu = new CPU();
|
||||
|
||||
updateValues();
|
||||
}
|
||||
|
||||
private void updateValues() {
|
||||
DefaultListModel<String> model = new DefaultListModel<String>();
|
||||
model.addElement("AF: 0x" + Integer.toHexString(cpu.getRegisters().readAF()));
|
||||
model.addElement("BC: 0x" + Integer.toHexString(cpu.getRegisters().readBC()));
|
||||
model.addElement("DE: 0x" + Integer.toHexString(cpu.getRegisters().readDE()));
|
||||
model.addElement("HL: 0x" + Integer.toHexString(cpu.getRegisters().readHL()));
|
||||
|
||||
registerList.setModel(model);
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
frmCpuDebugger = new JFrame();
|
||||
frmCpuDebugger.setTitle("CPU Debugger");
|
||||
frmCpuDebugger.setBounds(100, 100, 350, 350);
|
||||
frmCpuDebugger.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JButton btnStep = new JButton("Step");
|
||||
|
||||
JButton btnReset = new JButton("Reset");
|
||||
|
||||
JLabel lblRegisters = new JLabel("Registers:");
|
||||
|
||||
registerList = new JList<String>();
|
||||
GroupLayout groupLayout = new GroupLayout(frmCpuDebugger.getContentPane());
|
||||
groupLayout.setHorizontalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addComponent(registerList, GroupLayout.DEFAULT_SIZE, 314, Short.MAX_VALUE)
|
||||
.addComponent(lblRegisters)
|
||||
.addGroup(Alignment.TRAILING, groupLayout.createSequentialGroup()
|
||||
.addComponent(btnStep)
|
||||
.addPreferredGap(ComponentPlacement.RELATED, 198, Short.MAX_VALUE)
|
||||
.addComponent(btnReset)))
|
||||
.addContainerGap())
|
||||
);
|
||||
groupLayout.setVerticalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(lblRegisters)
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 195, GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(51)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(btnReset)
|
||||
.addComponent(btnStep))
|
||||
.addContainerGap())
|
||||
);
|
||||
frmCpuDebugger.getContentPane().setLayout(groupLayout);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
package playingcoffee.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.LayoutStyle.ComponentPlacement;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
|
||||
import playingcoffee.core.CPU;
|
||||
import playingcoffee.core.MMU;
|
||||
|
||||
public class CPUDebugger {
|
||||
|
||||
private JFrame frmCpuDebugger;
|
||||
private JList<String> registerList;
|
||||
|
||||
private MMU mmu;
|
||||
private CPU cpu;
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
CPUDebugger window = new CPUDebugger();
|
||||
window.frmCpuDebugger.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CPUDebugger() {
|
||||
initialize();
|
||||
|
||||
mmu = new MMU();
|
||||
cpu = new CPU();
|
||||
|
||||
updateValues();
|
||||
}
|
||||
|
||||
private void updateValues() {
|
||||
DefaultListModel<String> model = new DefaultListModel<String>();
|
||||
model.addElement("AF: 0x" + Integer.toHexString(cpu.getRegisters().readAF()));
|
||||
model.addElement("BC: 0x" + Integer.toHexString(cpu.getRegisters().readBC()));
|
||||
model.addElement("DE: 0x" + Integer.toHexString(cpu.getRegisters().readDE()));
|
||||
model.addElement("HL: 0x" + Integer.toHexString(cpu.getRegisters().readHL()));
|
||||
|
||||
registerList.setModel(model);
|
||||
|
||||
int data[][] = {
|
||||
{},
|
||||
};
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
frmCpuDebugger = new JFrame();
|
||||
frmCpuDebugger.setTitle("CPU Debugger");
|
||||
frmCpuDebugger.setBounds(100, 100, 350, 350);
|
||||
frmCpuDebugger.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JButton btnStep = new JButton("Step");
|
||||
|
||||
JButton btnReset = new JButton("Reset");
|
||||
|
||||
JLabel lblRegisters = new JLabel("Registers:");
|
||||
|
||||
registerList = new JList<String>();
|
||||
GroupLayout groupLayout = new GroupLayout(frmCpuDebugger.getContentPane());
|
||||
groupLayout.setHorizontalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addComponent(registerList, GroupLayout.DEFAULT_SIZE, 314, Short.MAX_VALUE)
|
||||
.addComponent(lblRegisters)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addComponent(btnStep)
|
||||
.addPreferredGap(ComponentPlacement.RELATED, 198, Short.MAX_VALUE)
|
||||
.addComponent(btnReset)))
|
||||
.addContainerGap())
|
||||
);
|
||||
groupLayout.setVerticalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(lblRegisters)
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 195, GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(51)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(btnStep)
|
||||
.addComponent(btnReset))
|
||||
.addContainerGap())
|
||||
);
|
||||
frmCpuDebugger.getContentPane().setLayout(groupLayout);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
private int cycles = 0;
|
||||
|
||||
public static int[] instructionCycle = {
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 20, 8, 8, 8, 4, 4, 8, 4,
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 12, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4
|
||||
};
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
if (cycles == 0) {
|
||||
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
cycles--;
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
// Apply cycle count
|
||||
|
||||
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x7C:
|
||||
registers.setFlag(Registers.FLAG_Z, (registers.readH() & (1 << 7)) == 0);
|
||||
registers.setFlag(Registers.FLAG_N, false);
|
||||
registers.setFlag(Registers.FLAG_H, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
|
||||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
private int cycles = 0;
|
||||
|
||||
public static int[] instructionCycle = {
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 20, 8, 8, 8, 4, 4, 8, 4,
|
||||
4, 12, 8, 8, 4, 4, 8, 4, 12, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
|
||||
8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
|
||||
8, 12, 12, 16, 12, 16, 8, 16, 8, 16, 12, 4, 12, 24, 8, 16,
|
||||
8, 12, 12, -1, 12, 16, 8, 16, 8, 16, 12, -1, 12, -1, 8, 16,
|
||||
12, 12, 8, -1, -1, 16, 8, 16, 16, 4, 16, -1, -1, -1, 8, 16,
|
||||
12, 12, 8, 4, -1, 16, 8, 16, 12, 8, 16, 4, -1, -1, 8, 16
|
||||
};
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
if (cycles == 0) {
|
||||
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
decodeOpcode(opcode);
|
||||
}
|
||||
cycles--;
|
||||
}
|
||||
|
||||
public void decodeOpcode(int opcode) {
|
||||
// Apply cycle count
|
||||
cycles += instructionCycle[opcode]
|
||||
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21: // LD HL, d16
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31: // LD SP, d16
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0x32: // LD (HL-), A
|
||||
mmu.write(registers.readA(), registers.readHL());
|
||||
registers.writeHL(registers.readHL() - 1);
|
||||
break;
|
||||
|
||||
case 0xAF: // XOR A
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
registers.setFlag(Registers.FLAG_Z, registers.readA() == 0);
|
||||
break;
|
||||
|
||||
case 0xCB: // CB - prefix
|
||||
decodePrefixedOpcode(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0x%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodePrefixedOpcode(int opcode) {
|
||||
switch (opcode) {
|
||||
case 0x7C:
|
||||
registers.setFlag(Registers.FLAG_Z, (registers.readH() & (1 << 7)) == 0);
|
||||
registers.setFlag(Registers.FLAG_N, false);
|
||||
registers.setFlag(Registers.FLAG_H, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.printf("Unknown opcode: 0xcb%2x\n", opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class Opcode {
|
||||
|
||||
private Op[] ops;
|
||||
|
||||
private final Registers registers;
|
||||
private final MMU mmu;
|
||||
|
||||
private int operand;
|
||||
|
||||
public Opcode(Registers registers, MMU mmu, Op... ops) {
|
||||
this.registers = registers;
|
||||
this.mmu = mmu;
|
||||
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public void execute(Registers regs, MMU mmu) {
|
||||
for (Op op : ops)
|
||||
op.execute();
|
||||
}
|
||||
|
||||
public interface Op {
|
||||
|
||||
public void execute();
|
||||
|
||||
}
|
||||
|
||||
public class Read16BitOperand implements Op {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
operand = (mmu.read(registers.pc++) << 8) | mmu.read(registers.pc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
package playingcoffee.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.LayoutStyle.ComponentPlacement;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
|
||||
import playingcoffee.core.CPU;
|
||||
import playingcoffee.core.MMU;
|
||||
|
||||
public class CPUDebugger {
|
||||
|
||||
private JFrame frame;
|
||||
private JTable memoryViewTable;
|
||||
private JList<String> registerList;
|
||||
|
||||
private MMU mmu;
|
||||
private CPU cpu;
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
CPUDebugger window = new CPUDebugger();
|
||||
window.frame.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CPUDebugger() {
|
||||
initialize();
|
||||
|
||||
mmu = new MMU();
|
||||
cpu = new CPU();
|
||||
|
||||
updateValues();
|
||||
}
|
||||
|
||||
private void updateValues() {
|
||||
ListModel<String> model = new
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
frame = new JFrame();
|
||||
frame.setBounds(100, 100, 750, 500);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JButton btnStep = new JButton("Step");
|
||||
|
||||
JButton btnReset = new JButton("Reset");
|
||||
|
||||
JLabel lblRegisters = new JLabel("Registers:");
|
||||
|
||||
registerList = new JList<String>();
|
||||
|
||||
memoryViewTable = new JTable();
|
||||
|
||||
JLabel lblMemoryView = new JLabel("Memory View:");
|
||||
GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
|
||||
groupLayout.setHorizontalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addComponent(btnStep)
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(btnReset))
|
||||
.addComponent(lblRegisters)
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 122, GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(18)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addComponent(lblMemoryView)
|
||||
.addComponent(memoryViewTable, GroupLayout.DEFAULT_SIZE, 574, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
groupLayout.setVerticalGroup(
|
||||
groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(lblRegisters)
|
||||
.addComponent(lblMemoryView))
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addGap(8)
|
||||
.addComponent(memoryViewTable, GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE))
|
||||
.addGroup(groupLayout.createSequentialGroup()
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 195, GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(18)
|
||||
.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
|
||||
.addComponent(btnStep)
|
||||
.addComponent(btnReset))
|
||||
.addGap(5))
|
||||
);
|
||||
frame.getContentPane().setLayout(groupLayout);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
package playingcoffee.core;
|
||||
|
||||
public class CPU {
|
||||
|
||||
private final MMU mmu;
|
||||
|
||||
private Registers registers;
|
||||
|
||||
public CPU(final MMU mmu) {
|
||||
this.mmu = mmu;
|
||||
|
||||
registers = new Registers();
|
||||
}
|
||||
|
||||
public Registers getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
int opcode = mmu.read(registers.pc++);
|
||||
System.out.printf("Fetched opcode: 0x%02x\n", opcode);
|
||||
|
||||
// Basic CPU implementation.
|
||||
// This will be changed in the future.
|
||||
switch (opcode) {
|
||||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x21:
|
||||
registers.writeL(mmu.read(registers.pc++));
|
||||
registers.writeH(mmu.read(registers.pc++));
|
||||
break;
|
||||
|
||||
case 0x31:
|
||||
registers.sp = mmu.read(registers.pc++) | (mmu.read(registers.pc++) << 8);
|
||||
break;
|
||||
|
||||
case 0xAF:
|
||||
registers.writeA(registers.readA() ^ registers.readA());
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue