aboutsummaryrefslogtreecommitdiffstats
path: root/src/Processor.cpp
diff options
context:
space:
mode:
authorkotorifan <kotorifan05@gmail.com>2026-01-23 15:15:48 +0100
committerkotorifan <kotorifan05@gmail.com>2026-02-04 09:02:16 +0100
commit32837712fedf4557ff44df7d5b8ddbd40c5f7990 (patch)
tree671d2b82f45d5e6de70ac5d15f59ea94b884d4b6 /src/Processor.cpp
downloadgameboy-32837712fedf4557ff44df7d5b8ddbd40c5f7990.tar.gz
Stupid problems with the old git repo. New one, unfortunately.
Diffstat (limited to 'src/Processor.cpp')
-rw-r--r--src/Processor.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/Processor.cpp b/src/Processor.cpp
new file mode 100644
index 0000000..38cf9ba
--- /dev/null
+++ b/src/Processor.cpp
@@ -0,0 +1,243 @@
+/** @file Processor.cpp */
+
+#include <memory>
+#include <fstream>
+#include <string>
+#include <stdexcept>
+#include <unordered_map>
+#include <cstdlib>
+#include <bitset>
+#include <iostream>
+
+#include "Processor.hpp"
+#include "Memory.hpp"
+#include "Common.hpp"
+
+/** * @name Register shorthands
+ * These macros are there so I don't have to write out
+ * the whole union's name every time I want to access
+ * a register.
+ * @{
+ */
+#define R_A sm83.af.byte.higher
+#define R_F sm83.af.byte.lower
+#define R_AF sm83.af.word
+#define R_H sm83.hl.byte.higher
+#define R_L sm83.hl.byte.lower
+#define R_HL sm83.hl.word
+#define R_D sm83.de.byte.higher
+#define R_E sm83.de.byte.lower
+#define R_DE sm83.de.word
+#define R_B sm83.bc.byte.higher
+#define R_C sm83.bc.byte.lower
+#define R_BC sm83.bc.word
+#define R_PC sm83.pc
+#define R_SP sm83.sp
+/** @} */
+
+/** * @name Flag shorthands
+ * Same as with the register shorthands, just
+ * convenience.
+ * @{
+ */
+#define F_CARRY 4
+#define F_HALF_CARRY 5
+#define F_SUBSTRACTION 6
+#define F_ZERO 7
+/** @} */
+
+#define ADD_CYC(val) add_cycles(cycles, val)
+
+namespace DMG01
+{
+
+ inline void SM83::add_cycles(Cycles& cycles, const uint32_t count)
+ {
+ cycles.total_cycles += count;
+ }
+
+ inline void SM83::set_flag(uint8_t& f, const uint8_t index, const bool on)
+ {
+ std::bitset<8>(f).set(index, on);
+ }
+
+ inline bool SM83::test_flag(uint8_t& f, const uint8_t index)
+ {
+ return std::bitset<8>(f).test(index);
+ }
+
+ /*
+ @brief Loads the ROM/executable into the emulator
+ */
+ void SM83::load_bin(const std::string& filename, Memory& memory)
+ {
+ std::ifstream f((filename), std::ios_base::binary);
+ if(!f) throw std::runtime_error("Failed to open the file");
+ f.seekg(0, std::ios_base::end);
+ auto f_size = f.tellg();
+ f.seekg(0, std::ios_base::beg);
+ f.read(reinterpret_cast<char*>(memory.space.get()), f_size);
+ }
+
+ template <typename T1, typename T2>
+ inline void SM83::ld_imm(T1& reg, const T2& data)
+ {
+ reg = static_cast<T1>(data);
+ }
+
+ template <typename T1, typename T2>
+ inline void SM83::ld_reg(T1& reg1, const T2& reg2)
+ {
+ reg1 = reg2;
+ }
+
+ template <typename T>
+ inline void SM83::inc_reg(T& val)
+ {
+ val++;
+ }
+
+ template <typename T>
+ inline void SM83::dec_reg(T& val)
+ {
+ val--;
+ }
+
+ inline void SM83::rlca(SM83& sm83)
+ {
+ R_A = (R_A >> 1 | R_A << 7);
+ if(sm83.test_flag(R_F, F_CARRY))
+ sm83.set_flag(R_F, F_CARRY, true);
+ else if(sm83.test_flag(R_F, F_CARRY))
+ sm83.set_flag(R_F, F_CARRY, false);
+ }
+
+ template <typename T1, typename T2>
+ inline void SM83::add_reg(T1& aug, const T2& add)
+ {
+ aug =+ add;
+ }
+
+ inline void SM83::rrca(SM83& sm83)
+ {
+ R_A = (R_A << 1 | R_A >> 7);
+ if(sm83.test_flag(R_F, F_CARRY))
+ sm83.set_flag(R_F, F_CARRY, true);
+ else if(sm83.test_flag(R_F, F_CARRY))
+ sm83.set_flag(R_F, F_CARRY, false);
+ }
+
+ inline void SM83::stop(SM83& sm83, Memory& memory)
+ {
+ R_PC++;
+ memory.space[0xff04] = 0x00;
+ sm83.stop_state = true;
+ }
+ /*
+ @brief Processes opcodes and calls the according function
+ @param opcode The opcode it should process
+ */
+ void SM83::process_opcodes(const uint8_t opcode, Memory& memory, SM83& sm83)
+ {
+ switch(opcode)
+ {
+ case 0x00: /* NOP */
+ ADD_CYC(4);
+ break;
+ case 0x01: /* LD BC, n16 */
+ ld_imm(R_BC, memory.space[R_PC++]);
+ ADD_CYC(12);
+ break;
+ case 0x02: /* LD (BC), A */
+ ld_reg(memory.space[R_BC], R_A);
+ ADD_CYC(8);
+ break;
+ case 0x03: /* INC BC */
+ inc_reg(R_BC);
+ ADD_CYC(8);
+ break;
+ case 0x04: /* INC B */
+ inc_reg(R_B);
+ ADD_CYC(4);
+ break;
+ case 0x05: /* DEC B */
+ dec_reg(R_B);
+ ADD_CYC(4);
+ break;
+ case 0x06: /* LD B, d6 */
+ ld_imm(R_B, memory.space[R_PC++]);
+ ADD_CYC(8);
+ break;
+ case 0x07: /* RLCA */
+ rlca(sm83);
+ ADD_CYC(4);
+ break;
+ case 0x08: /* LD (a16), SP */
+ ld_imm(memory.space[R_PC++], R_SP);
+ ADD_CYC(20);
+ break;
+ case 0x09:
+ add_reg(R_HL, R_BC);
+ ADD_CYC(8);
+ break;
+ case 0x0a:
+ ld_reg(R_A, memory.space[R_BC]);
+ ADD_CYC(8);
+ break;
+ case 0x0b:
+ dec_reg(R_BC);
+ ADD_CYC(8);
+ break;
+ case 0x0c:
+ inc_reg(R_C);
+ ADD_CYC(4);
+ break;
+ case 0x0d:
+ dec_reg(R_C);
+ ADD_CYC(4);
+ break;
+ case 0x0e:
+ ld_imm(R_C, memory.space[R_PC++]);
+ ADD_CYC(8);
+ break;
+ case 0x0f:
+ rrca(sm83);
+ ADD_CYC(4);
+ break;
+ case 0x10:
+ stop(sm83, memory);
+ ADD_CYC(4);
+ break;
+ case 0x11:
+ ld_imm(R_DE, memory.space[R_PC++]);
+ ADD_CYC(12);
+ break;
+ case 0x12:
+ ld_imm(memory.space[R_DE], R_A);
+ ADD_CYC(8);
+ break;
+ case 0x13:
+ inc_reg(R_DE);
+ ADD_CYC(8);
+ break;
+ case 0x14:
+ inc_reg(R_D);
+ ADD_CYC(4);
+ break;
+ case 0x15:
+ dec_reg(R_D);
+ ADD_CYC(4);
+ break;
+ case 0x16:
+ ld_reg(R_DE, memory.space[R_PC++]);
+ ADD_CYC(8);
+ break;
+ case 0x017:
+ ADD_CYC
+ break;
+ default:
+ std::cout << "The program has seemingly run into an unrecognized opcode\n";
+ break;
+ }
+ }
+}