From 5aa8a648718ee86dbe5a9993e169616c84627790 Mon Sep 17 00:00:00 2001
From: Lauchmelder <robert.trololo@gmail.com>
Date: Wed, 20 Oct 2021 22:39:29 +0200
Subject: [PATCH] Initial commit

---
 .gitignore                  |  3 ++
 CMakeLists.txt              |  9 +++++
 NES Emulator/CMakeLists.txt |  3 ++
 NES Emulator/bus.c          | 77 +++++++++++++++++++++++++++++++++++++
 NES Emulator/bus.h          | 28 ++++++++++++++
 NES Emulator/cartridge.c    | 25 ++++++++++++
 NES Emulator/cartridge.h    | 18 +++++++++
 NES Emulator/cpu.c          | 23 +++++++++++
 NES Emulator/cpu.h          | 38 ++++++++++++++++++
 NES Emulator/main.c         |  9 +++++
 NES Emulator/types.h        | 10 +++++
 11 files changed, 243 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 CMakeLists.txt
 create mode 100644 NES Emulator/CMakeLists.txt
 create mode 100644 NES Emulator/bus.c
 create mode 100644 NES Emulator/bus.h
 create mode 100644 NES Emulator/cartridge.c
 create mode 100644 NES Emulator/cartridge.h
 create mode 100644 NES Emulator/cpu.c
 create mode 100644 NES Emulator/cpu.h
 create mode 100644 NES Emulator/main.c
 create mode 100644 NES Emulator/types.h

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a5c2d2d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.vs/
+out/
+*.json
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..f6dd089
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,9 @@
+# CMakeList.txt: CMake-Projektdatei der obersten Ebene. Führen Sie hier die globale Konfiguration aus,
+# und schließen Sie Unterprojekte ein.
+#
+cmake_minimum_required (VERSION 3.8)
+
+project ("NES Emulator")
+
+# Schließen Sie Unterprojekte ein.
+add_subdirectory ("NES Emulator")
diff --git a/NES Emulator/CMakeLists.txt b/NES Emulator/CMakeLists.txt
new file mode 100644
index 0000000..257ec8b
--- /dev/null
+++ b/NES Emulator/CMakeLists.txt	
@@ -0,0 +1,3 @@
+cmake_minimum_required (VERSION 3.8)
+
+add_executable (CMakeTarget "main.c"  "cpu.h" "types.h" "bus.h" "bus.c" "cartridge.h" "cpu.c" "cartridge.c")
diff --git a/NES Emulator/bus.c b/NES Emulator/bus.c
new file mode 100644
index 0000000..9410ed8
--- /dev/null
+++ b/NES Emulator/bus.c	
@@ -0,0 +1,77 @@
+#include "bus.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cpu.h"
+#include "cartridge.h"
+
+struct Bus* createBus()
+{
+	struct Bus* bus = (struct Bus*)malloc(sizeof(struct Bus));
+	if (bus == NULL)
+	{
+		fprintf(stderr, "Failed to create Bus object, aborting.");
+		exit(1);
+	}
+
+	// 2KB of memory, equates to 2048 Bytes (0x800)
+	bus->ram = (Byte*)malloc(0x800);
+	if (bus->ram == NULL)
+	{
+		fprintf(stderr, "Failed to allocate memory for NES RAM, aborting.");
+		exit(1);
+	}
+
+	// Create CPU and attach it
+	bus->cpu = createCPU(bus);
+
+	// Create and insert cartridge
+	bus->cartridge = createCartridge(bus, "nestest.nes");
+
+	return bus;
+}
+
+void destroyBus(struct Bus* bus)
+{
+	destroyCartridge(bus->cartridge);
+	destroyCPU(bus->cpu);
+	
+	free(bus->ram);
+	free(bus);
+}
+
+Byte Read(struct Bus* bus, Word addr)
+{
+	// Return from the appropriate device depending on the address
+	if (addr <= 0x1FFF)	// RAM (or one of the mirrored addresses)
+	{
+		return bus->ram[addr & 0x7FF];
+	}
+	else if (0x4020 <= addr && addr <= 0xFFFF)	// Cartridge space
+	{
+		// rom->read()
+	}
+	else
+	{
+		fprintf(stderr, "Access violation at $%x", addr);
+		exit(1);
+	}
+}
+
+void Write(struct Bus* bus, Word addr, Byte val)
+{
+	// Write to the appropriate memory or device
+	if (addr <= 0x1FFF)	// RAM (or one of the mirrored addresses)
+	{
+		bus->ram[addr & 0x7FF] = val;
+	}
+	else if (0x4020 <= addr && addr <= 0xFFFF)	// Cartridge space
+	{
+		// rom->write()
+	}
+	else
+	{
+		fprintf(stderr, "Access violation at $%x", addr);
+		exit(1);
+	}
+}
diff --git a/NES Emulator/bus.h b/NES Emulator/bus.h
new file mode 100644
index 0000000..92b29d4
--- /dev/null
+++ b/NES Emulator/bus.h	
@@ -0,0 +1,28 @@
+#ifndef _BUS_H_
+#define _BUS_H_
+
+#include "types.h"
+
+struct CPU;
+struct Cartridge;
+
+// Main communication path for devices and memory in the NES
+struct Bus
+{
+	Byte* ram;
+
+	struct CPU* cpu;
+	struct Cartridge* cartridge;
+};
+
+// Sets up the Bus, allocates memory and creates devices
+struct Bus* createBus();
+
+// Destroys the bus, cleans up memory and destroys devices on the Bus
+void destroyBus(struct Bus* bus);
+
+// Read/Write to and from the bus
+Byte Read(struct Bus* bus, Word addr);
+void Write(struct Bus* bus, Word addr, Byte val);
+
+#endif // _BUS_H_
\ No newline at end of file
diff --git a/NES Emulator/cartridge.c b/NES Emulator/cartridge.c
new file mode 100644
index 0000000..df37464
--- /dev/null
+++ b/NES Emulator/cartridge.c	
@@ -0,0 +1,25 @@
+#include "cartridge.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "bus.h"
+
+struct Cartridge* createCartridge(struct Bus* parent, const char* filepath)
+{
+	struct Cartridge* cartridge = (struct Cartridge*)malloc(sizeof(struct Cartridge));
+	if (cartridge == NULL)
+	{
+		fprintf(stderr, "Failed to create cartridge.\n");
+		exit(1);
+	}
+
+	cartridge->memory = NULL;
+	cartridge->bus = parent;
+	return cartridge;
+}
+
+void destroyCartridge(struct Cartridge* cartridge)
+{
+	// free(cartridge->memory);
+	free(cartridge);
+}
diff --git a/NES Emulator/cartridge.h b/NES Emulator/cartridge.h
new file mode 100644
index 0000000..fb9dc64
--- /dev/null
+++ b/NES Emulator/cartridge.h	
@@ -0,0 +1,18 @@
+#ifndef _CARTRIDGE_H_
+#define _CARTRIDGE_H_
+
+#include "types.h"
+
+struct Bus;
+
+struct Cartridge
+{
+	Byte* memory;
+
+	struct Bus* bus;
+};
+
+struct Cartridge* createCartridge(struct Bus* parent, const char* filepath);
+void destroyCartridge(struct Cartridge* cartridge);
+
+#endif //_CARTRIDGE_H_
\ No newline at end of file
diff --git a/NES Emulator/cpu.c b/NES Emulator/cpu.c
new file mode 100644
index 0000000..2d57c40
--- /dev/null
+++ b/NES Emulator/cpu.c	
@@ -0,0 +1,23 @@
+#include "cpu.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "bus.h"
+
+struct CPU* createCPU(struct Bus* parent)
+{
+	struct CPU* cpu = (struct CPU*)malloc(sizeof(struct CPU));
+	if (cpu == NULL)
+	{
+		fprintf(stderr, "Failed to create CPU, aborting.\n");
+		exit(1);
+	}
+
+	cpu->bus = parent;
+	return cpu;
+}
+
+void destroyCPU(struct CPU* cpu)
+{
+	free(cpu);
+}
diff --git a/NES Emulator/cpu.h b/NES Emulator/cpu.h
new file mode 100644
index 0000000..3a7e88e
--- /dev/null
+++ b/NES Emulator/cpu.h	
@@ -0,0 +1,38 @@
+#ifndef _CPU_H_
+#define _CPU_H_
+
+#include "types.h"
+
+struct Bus;
+
+struct CPU
+{
+	Byte acc;
+	Byte x, y;
+	Byte sp;
+
+	union
+	{
+		struct
+		{
+			Byte carry : 1;
+			Byte zero : 1;
+			Byte id : 1;
+			Byte decimal : 1;
+			Byte unused : 2;
+			Byte overflow : 1;
+			Byte negative : 1;
+		};
+
+		Byte raw;
+	} status;
+
+	Word pc;
+
+	struct Bus* bus;
+};
+
+struct CPU* createCPU(struct Bus* parent);
+void destroyCPU(struct CPU* cpu);
+
+#endif // _CPU_H_
\ No newline at end of file
diff --git a/NES Emulator/main.c b/NES Emulator/main.c
new file mode 100644
index 0000000..2087b1f
--- /dev/null
+++ b/NES Emulator/main.c	
@@ -0,0 +1,9 @@
+#include "bus.h"
+
+int main()
+{
+	struct Bus* bus = createBus();
+	destroyBus(bus);
+
+	return 0;
+}
diff --git a/NES Emulator/types.h b/NES Emulator/types.h
new file mode 100644
index 0000000..8770d55
--- /dev/null
+++ b/NES Emulator/types.h	
@@ -0,0 +1,10 @@
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+#include <stdint.h>
+
+typedef uint8_t Byte;
+typedef uint16_t Word;
+typedef uint32_t DWord;
+
+#endif // _TYPES_H_
\ No newline at end of file