Initial Commit

main
aieque 2020-12-23 19:29:59 +01:00
commit a0ff1cf91a
501 changed files with 27535 additions and 0 deletions

0
.metadata/.lock 100644
View File

125
.metadata/.log 100644
View File

@ -0,0 +1,125 @@
!SESSION 2020-12-23 07:02:50.204 -----------------------------------------------
eclipse.buildId=4.13.0.I20190916-1045
java.version=1.8.0_91
java.vendor=Oracle Corporation
BootLoader constants: OS=win32, ARCH=x86_64, WS=win32, NL=en_GB
Framework arguments: -product org.eclipse.epp.package.java.product
Command-line arguments: -os win32 -ws win32 -arch x86_64 -product org.eclipse.epp.package.java.product
!ENTRY org.eclipse.jface 2 0 2020-12-23 07:03:40.945
!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation.
!SUBENTRY 1 org.eclipse.jface 2 0 2020-12-23 07:03:40.946
!MESSAGE A conflict occurred for ALT+T:
Binding(ALT+T,
ParameterizedCommand(Command(org.synthclipse.ide.command.TimelineShowView,Timeline / Show View,
,
Category(org.synthclipse.category,Synthclipse,null,true),
org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@4b4228cf,
,,true),null),
org.eclipse.ui.defaultAcceleratorConfiguration,
org.eclipse.ui.contexts.window,,,system)
Binding(ALT+T,
ParameterizedCommand(Command(org.synthclipse.ide.command.GraphShowView,Graph / Show View,
,
Category(org.synthclipse.category,Synthclipse,null,true),
org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@7d216ee8,
,,true),null),
org.eclipse.ui.defaultAcceleratorConfiguration,
org.eclipse.ui.contexts.window,,,system)
!ENTRY org.eclipse.equinox.p2.metadata.repository 4 1000 2020-12-23 07:39:51.272
!MESSAGE No repository found at jar:file:/E:/pdf/jd-eclipse-2.0.0.zip!/.
!ENTRY org.synthclipse.ide 4 0 2020-12-23 18:07:12.040
!MESSAGE java.lang.UnsatisfiedLinkError: no JSyphon in java.library.path
!STACK 0
java.lang.UnsatisfiedLinkError: no JSyphon in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
at jsyphon.JSyphonServer.<clinit>(JSyphonServer.java:40)
at org.synthclipse.ide.controllers.SharingController.<init>(SharingController.java:54)
at org.synthclipse.ide.controllers.SynthclipseController.<init>(SynthclipseController.java:125)
at org.synthclipse.ide.controllers.SynthclipseController.<init>(SynthclipseController.java:153)
at org.synthclipse.ide.controllers.SynthclipseController$SingletonHolder.<clinit>(SynthclipseController.java:157)
at org.synthclipse.ide.controllers.SynthclipseController.getInstance(SynthclipseController.java:161)
at org.synthclipse.ide.Activator.start(Activator.java:87)
at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:842)
at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:1)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:834)
at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:791)
at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:1015)
at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:365)
at org.eclipse.osgi.container.Module.doStart(Module.java:603)
at org.eclipse.osgi.container.Module.start(Module.java:467)
at org.eclipse.osgi.framework.util.SecureAction$23.run(SecureAction.java:500)
at org.eclipse.osgi.framework.util.SecureAction$23.run(SecureAction.java:1)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:497)
at org.eclipse.osgi.internal.hooks.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:117)
at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:571)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:330)
at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:398)
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:476)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:425)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:417)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:155)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.eclipse.osgi.internal.framework.EquinoxBundle.loadClass(EquinoxBundle.java:620)
at org.eclipse.core.internal.registry.osgi.RegistryStrategyOSGI.createExecutableExtension(RegistryStrategyOSGI.java:196)
at org.eclipse.core.internal.registry.ExtensionRegistry.createExecutableExtension(ExtensionRegistry.java:934)
at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:246)
at org.eclipse.core.internal.registry.ConfigurationElementHandle.createExecutableExtension(ConfigurationElementHandle.java:63)
at org.eclipse.ui.internal.handlers.HandlerProxy.loadHandler(HandlerProxy.java:342)
at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:277)
at org.eclipse.ui.internal.handlers.E4HandlerProxy.execute(E4HandlerProxy.java:95)
at sun.reflect.GeneratedMethodAccessor54.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
at org.eclipse.e4.core.internal.di.InjectorImpl.invokeUsingClass(InjectorImpl.java:318)
at org.eclipse.e4.core.internal.di.InjectorImpl.invoke(InjectorImpl.java:252)
at org.eclipse.e4.core.contexts.ContextInjectionFactory.invoke(ContextInjectionFactory.java:173)
at org.eclipse.e4.core.commands.internal.HandlerServiceHandler.execute(HandlerServiceHandler.java:156)
at org.eclipse.core.commands.Command.executeWithChecks(Command.java:498)
at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:487)
at org.eclipse.e4.core.commands.internal.HandlerServiceImpl.executeHandler(HandlerServiceImpl.java:213)
at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.executeCommand(KeyBindingDispatcher.java:308)
at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.press(KeyBindingDispatcher.java:584)
at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.processKeyEvent(KeyBindingDispatcher.java:653)
at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.filterKeySequenceBindings(KeyBindingDispatcher.java:443)
at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.access$2(KeyBindingDispatcher.java:386)
at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher$KeyDownFilter.handleEvent(KeyBindingDispatcher.java:96)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1199)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1056)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1081)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1066)
at org.eclipse.swt.widgets.Control.traverse(Control.java:4270)
at org.eclipse.swt.widgets.Control.translateTraversal(Control.java:4252)
at org.eclipse.swt.widgets.Composite.translateTraversal(Composite.java:1299)
at org.eclipse.swt.widgets.Display.translateTraversal(Display.java:4729)
at org.eclipse.swt.widgets.Display.filterMessage(Display.java:1217)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3581)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1160)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1049)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:633)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:557)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:150)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:150)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:400)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:660)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:597)
at org.eclipse.equinox.launcher.Main.run(Main.java:1468)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,43 @@
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;
}
}
}

View File

@ -0,0 +1,5 @@
package playingcoffee.core;
public class Registers {
}

View File

@ -0,0 +1,35 @@
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:
}
}
}

View File

@ -0,0 +1,12 @@
package playingcoffee.core;
public class CPU {
public CPU() {
}
public void clock() {
}
}

View File

@ -0,0 +1,5 @@
package playingcoffee.core.cpu;
public class MicroOps {
}

View File

@ -0,0 +1,35 @@
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];
}
}

View File

@ -0,0 +1,35 @@
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();;
}
}
}

View File

@ -0,0 +1,112 @@
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);
}
}

View File

@ -0,0 +1,108 @@
// 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);
}
}
}

View File

@ -0,0 +1,14 @@
package playingcoffee.core;
public class CPU {
private final Memory memory;
public CPU() {
}
public void clock() {
}
}

View File

@ -0,0 +1,11 @@
package playingcoffee.core;
public class CPU {
private Registers registers;
public Registers getRegisters() {
return registers;
}
}

View File

@ -0,0 +1,93 @@
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;
}
}

View File

@ -0,0 +1,5 @@
package playingcoffee.core;
public class Memory {
}

View File

@ -0,0 +1,123 @@
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;
}
}

View File

@ -0,0 +1,68 @@
// 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);
}
}
}

View File

@ -0,0 +1,16 @@
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>();
}
}

View File

@ -0,0 +1,23 @@
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() {
}
}

View File

@ -0,0 +1,103 @@
// 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);
}
}
}

View File

@ -0,0 +1,17 @@
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];
}
}

View File

@ -0,0 +1,110 @@
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);
}
}

View File

@ -0,0 +1,50 @@
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;
}
}
}

View File

@ -0,0 +1,106 @@
// 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);
}
}
}

View File

@ -0,0 +1,46 @@
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;
}
}
}

View File

@ -0,0 +1,9 @@
package playingcoffee.core.cpu;
public class Opcode {
public Opcode(MicroOp ops...) {
}
}

View File

@ -0,0 +1,12 @@
package playingcoffee.core.cpu;
public abstract class MicroOp {
private int cycles;
public int getLength() {
return cycles;
}
public abstract void execute();
}

View File

@ -0,0 +1,80 @@
// 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);
}
}
}

View File

@ -0,0 +1,5 @@
package playingcoffee.core.cpu;
public class Opcode {
}

View File

@ -0,0 +1,113 @@
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;
}
}

View File

@ -0,0 +1,53 @@
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;
}
}
}

View File

@ -0,0 +1,118 @@
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);
}
}

View File

@ -0,0 +1,120 @@
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);
}
}

View File

@ -0,0 +1,93 @@
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;
}
}

View File

@ -0,0 +1,13 @@
package playingcoffee.core;
public class Gameboy {
private CPU m_CPU;
public Gameboy() {
m_CPU = new CPU();
}
}

View File

@ -0,0 +1,87 @@
// 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);
}
}
}

View File

@ -0,0 +1,94 @@
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;
}
}

View File

@ -0,0 +1,17 @@
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();
}
}

View File

@ -0,0 +1,23 @@
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());
}
}

View File

@ -0,0 +1,25 @@
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 {
}
}

View File

@ -0,0 +1,21 @@
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() {
}
}

View File

@ -0,0 +1,22 @@
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 {
}
}

View File

@ -0,0 +1,17 @@
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);
}
}

View File

@ -0,0 +1,118 @@
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);
}
}

View File

@ -0,0 +1,106 @@
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);
}
}

View File

@ -0,0 +1,35 @@
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));
}
}
}

View File

@ -0,0 +1,68 @@
// 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);
}
}
}

View File

@ -0,0 +1,7 @@
package playingcoffee.core;
public class CPU {
}

View File

@ -0,0 +1,119 @@
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;
}
}

View File

@ -0,0 +1,38 @@
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);
}
}
}

View File

@ -0,0 +1,16 @@
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);
}
}

View File

@ -0,0 +1,123 @@
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;
}
}

View File

@ -0,0 +1,5 @@
package playingcoffee.core;
public class Op {
}

View File

@ -0,0 +1,72 @@
// 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);
}
}
}

View File

@ -0,0 +1,60 @@
// 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) {
}
}

View File

@ -0,0 +1,20 @@
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() {
}
}

View File

@ -0,0 +1,30 @@
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) {
}
}
}

View File

@ -0,0 +1,25 @@
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 {
}
}

View File

@ -0,0 +1,11 @@
package playingcoffee.core;
public class Gameboy {
private CPU m_CPU;
public Gameboy() {
m_CPU = new CPU();
}
}

View File

@ -0,0 +1,30 @@
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) {
}
}
}

View File

@ -0,0 +1,100 @@
// 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);
}
}
}

View File

@ -0,0 +1,15 @@
package playingcoffee.core;
public class Gameboy {
private CPU m_CPU;
public Gameboy() {
m_CPU = new CPU();
while (true) {
m_CPU.clock();
}
}
}

View File

@ -0,0 +1,5 @@
package playingcoffee.core.cpu;
public abstract class MicroOp {
}

View File

@ -0,0 +1,64 @@
// 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) {
}
}

View File

@ -0,0 +1,120 @@
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);
}
}

View File

@ -0,0 +1,16 @@
package playingcoffee.core;
import playingcoffee.core.Memory;
public class CPU {
private final Memory memory;
public CPU(Memory memory) {
this.memory = memory;
}
public void clock() {
}
}

View File

@ -0,0 +1,35 @@
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);
}
}
}

View File

@ -0,0 +1,25 @@
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);
}
}

View File

@ -0,0 +1,24 @@
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);
}
}

View File

@ -0,0 +1,38 @@
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 =
}
}
}

View File

@ -0,0 +1,36 @@
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) {
}
}
}

View File

@ -0,0 +1,30 @@
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) {
}
}
}

View File

@ -0,0 +1,24 @@
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++);
}
}

View File

@ -0,0 +1,93 @@
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;
}
}

View File

@ -0,0 +1,97 @@
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;
}
}

View File

@ -0,0 +1,72 @@
// 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);
}
}
}

View File

@ -0,0 +1,5 @@
package playingcoffee.core;
public class CPU {
}

View File

@ -0,0 +1,36 @@
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) {
}
}
}

View File

@ -0,0 +1,14 @@
package playingcoffee.core;
public class CPU {
private final Memory memory;
public CPU(Memory memory) {
this.memory = memory;
}
public void clock() {
}
}

View File

@ -0,0 +1,37 @@
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);
}
}
}

View File

@ -0,0 +1,48 @@
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;
}
}
}

View File

@ -0,0 +1,100 @@
// 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);
}
}
}

View File

@ -0,0 +1,15 @@
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];
}
}

View File

@ -0,0 +1,43 @@
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);
}
}

View File

@ -0,0 +1,110 @@
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);
}
}

View File

@ -0,0 +1,33 @@
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:
}
}
}

View File

@ -0,0 +1,36 @@
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;
}
}
}

View File

@ -0,0 +1,70 @@
// 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);
}
}
}

View File

@ -0,0 +1,39 @@
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
}

View File

@ -0,0 +1,79 @@
// 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);
}
}
}

View File

@ -0,0 +1,109 @@
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);
}
}

Some files were not shown because too many files have changed in this diff Show More