Restart GB Emulator
This commit is contained in:
parent
9032716346
commit
8b475cb4cf
|
@ -0,0 +1,14 @@
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct MemoryBus {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemoryBus {
|
||||||
|
pub fn read_byte(&self, _address: u16) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_byte(&self, _address: u16) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
398
src/cpu.rs
398
src/cpu.rs
|
@ -1,365 +1,91 @@
|
||||||
// use super::instructions::Instruction;
|
use super::bus::MemoryBus;
|
||||||
|
use std::ops::{Index, IndexMut};
|
||||||
|
use std::convert::From;
|
||||||
|
|
||||||
// Gameboy CPU
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct LR35902 {
|
pub struct LR35902 {
|
||||||
_sp: u16,
|
bus: MemoryBus,
|
||||||
_pc: u16,
|
registers: Registers,
|
||||||
_reg: Registers,
|
sp: u16, // Stack Pointer
|
||||||
|
pc: u16, // Program Counter
|
||||||
|
flag: Flag, // Flag Register
|
||||||
|
ime: bool, // Interrupt Master Enable Flag
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LR35902 {
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub fn cycle(&mut self) {
|
pub struct Flag {
|
||||||
let opcode = Self::fetch();
|
z: bool, // Zero Flag
|
||||||
self.decode(opcode);
|
n: bool, // Subtract Flag
|
||||||
Self::execute();
|
h: bool, // Half-Carry Flag
|
||||||
}
|
c: bool, // Carry Flag
|
||||||
|
}
|
||||||
|
|
||||||
fn fetch() -> u8 {
|
impl From<u8> for Flag {
|
||||||
unimplemented!()
|
fn from(num: u8) -> Self {
|
||||||
}
|
Flag {
|
||||||
|
z: (num >> 7) == 1,
|
||||||
fn decode(&mut self, opcode: u8) {
|
n: ((num >> 6) & 0x01) == 1,
|
||||||
// Source: https://gb-archive.github.io/salvage/decoding_gbz80_opcodes/Decoding%20Gamboy%20Z80%20Opcodes.html
|
h: ((num >> 5) & 0x01) == 1,
|
||||||
// x = the opcode's 1st octal digit (i.e. bits 7-6)
|
c: ((num >> 4) & 0x01) == 1,
|
||||||
// y = the opcode's 2nd octal digit (i.e. bits 5-3)
|
|
||||||
// z = the opcode's 3rd octal digit (i.e. bits 2-0)
|
|
||||||
// p = y right-shifted one position (i.e. bits 5-4)
|
|
||||||
// q = y modulo 2 (i.e. bit 3)
|
|
||||||
|
|
||||||
let x = opcode >> 6;
|
|
||||||
let y = (opcode & 0b00111000) >> 3; // 0b00111000 = 0x38
|
|
||||||
let z = opcode & 0b00000111; // 0b00000111 = 0x07
|
|
||||||
let p = y >> 1;
|
|
||||||
let q = y & 0b00000001; // 0b001 = 0x1;
|
|
||||||
|
|
||||||
let _d: i8 = 0; // Displacement Byte
|
|
||||||
let _n: u8 = 0; // 8-bit Immediate Operand
|
|
||||||
let _nn: u16 = 0; // 16-bit Immediate Operand
|
|
||||||
|
|
||||||
match (x, z, q, y, p) {
|
|
||||||
(0, 0, _, 0, _) => {}
|
|
||||||
_ => panic!("Unexpected Opcode!"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute() {
|
}
|
||||||
unimplemented!()
|
|
||||||
|
impl From<Flag> for u8 {
|
||||||
|
fn from(flag: Flag) -> Self {
|
||||||
|
(flag.z as u8) << 7 | (flag.n as u8) << 6 | (flag.h as u8) << 5 | (flag.c as u8) << 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Default)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Registers {
|
pub struct Registers {
|
||||||
a: u8, // Accumulator Register
|
a: u8,
|
||||||
b: u8,
|
b: u8,
|
||||||
c: u8,
|
c: u8,
|
||||||
d: u8,
|
d: u8,
|
||||||
e: u8,
|
e: u8,
|
||||||
h: u8,
|
h: u8,
|
||||||
l: u8,
|
l: u8,
|
||||||
f: Flag,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Registers {
|
impl Index<Register> for Registers {
|
||||||
pub fn set_af(&mut self, value: u16) {
|
type Output = u8;
|
||||||
let (high, low) = Self::split_u16(value);
|
|
||||||
|
|
||||||
self.a = high;
|
fn index(&self, index: Register) -> &Self::Output {
|
||||||
self.f = low.into();
|
match index {
|
||||||
}
|
Register::A => &self.a,
|
||||||
|
Register::B => &self.b,
|
||||||
pub fn get_af(&self) -> u16 {
|
Register::C => &self.c,
|
||||||
Self::merge_u8s(self.a, self.f.into())
|
Register::D => &self.d,
|
||||||
}
|
Register::E => &self.e,
|
||||||
|
Register::H => &self.h,
|
||||||
pub fn set_bc(&mut self, value: u16) {
|
Register::L => &self.l,
|
||||||
let (high, low) = Self::split_u16(value);
|
|
||||||
|
|
||||||
self.b = high;
|
|
||||||
self.c = low;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_bc(&self) -> u16 {
|
|
||||||
Self::merge_u8s(self.b, self.c)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_de(&mut self, value: u16) {
|
|
||||||
let (high, low) = Self::split_u16(value);
|
|
||||||
|
|
||||||
self.d = high;
|
|
||||||
self.e = low;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_de(&self) -> u16 {
|
|
||||||
Self::merge_u8s(self.d, self.e)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_hl(&mut self, value: u16) {
|
|
||||||
let (high, low) = Self::split_u16(value);
|
|
||||||
|
|
||||||
self.h = high;
|
|
||||||
self.l = low;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_hl(&self) -> u16 {
|
|
||||||
Self::merge_u8s(self.h, self.l)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_a(&mut self, a: u8) {
|
|
||||||
self.a = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_a(&self) -> u8 {
|
|
||||||
self.a
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_b(&mut self, b: u8) {
|
|
||||||
self.b = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_b(&self) -> u8 {
|
|
||||||
self.b
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_c(&mut self, c: u8) {
|
|
||||||
self.c = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_c(&self) -> u8 {
|
|
||||||
self.c
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_d(&mut self, d: u8) {
|
|
||||||
self.d = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_d(&self) -> u8 {
|
|
||||||
self.d
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_e(&mut self, e: u8) {
|
|
||||||
self.e = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_e(&self) -> u8 {
|
|
||||||
self.e
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_h(&mut self, h: u8) {
|
|
||||||
self.h = h;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_h(&self) -> u8 {
|
|
||||||
self.h
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_l(&mut self, l: u8) {
|
|
||||||
self.l = l;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_l(&self) -> u8 {
|
|
||||||
self.l
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_f<F: Into<Flag>>(&mut self, flag: F) {
|
|
||||||
self.f = flag.into();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_f(&self) -> Flag {
|
|
||||||
self.f
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_u8_f(&self) -> u8 {
|
|
||||||
self.f.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn split_u16(value: u16) -> (u8, u8) {
|
|
||||||
((value >> 8) as u8, value as u8)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn merge_u8s(left: u8, right: u8) -> u16 {
|
|
||||||
(left as u16) << 8 | right as u16
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Default)]
|
|
||||||
pub struct Flag(u8);
|
|
||||||
|
|
||||||
impl Flag {
|
|
||||||
pub fn get_zf(&self) -> bool {
|
|
||||||
(self.0 >> 7) == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_zf(&mut self, enabled: bool) {
|
|
||||||
if enabled {
|
|
||||||
self.0 |= 0b10000000; // Set
|
|
||||||
} else {
|
|
||||||
self.0 &= 0b01111111; // Clear
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_n(&self) -> bool {
|
|
||||||
((self.0 >> 6) & 0x01) == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_n(&mut self, enabled: bool) {
|
|
||||||
if enabled {
|
|
||||||
self.0 |= 0b01000000; // Set
|
|
||||||
} else {
|
|
||||||
self.0 &= 0b10111111; // Clear
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_h(&self) -> bool {
|
|
||||||
((self.0 >> 5) & 0x01) == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_h(&mut self, enabled: bool) {
|
|
||||||
if enabled {
|
|
||||||
self.0 |= 0b00100000; // Set
|
|
||||||
} else {
|
|
||||||
self.0 &= 0b11011111; // Clear
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_cy(&self) -> bool {
|
|
||||||
((self.0 >> 4) & 0x01) == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_cy(&mut self, enabled: bool) {
|
|
||||||
if enabled {
|
|
||||||
self.0 |= 0b00010000; // Set
|
|
||||||
} else {
|
|
||||||
self.0 &= 0b11101111; // Clear
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u8> for Flag {
|
impl IndexMut<Register> for Registers {
|
||||||
fn from(value: u8) -> Self {
|
fn index_mut(&mut self, index: Register) -> &mut Self::Output {
|
||||||
Self(value & 0xF0) // Throw out bits 0 -> 3
|
match index {
|
||||||
|
Register::A => &mut self.a,
|
||||||
|
Register::B => &mut self.b,
|
||||||
|
Register::C => &mut self.c,
|
||||||
|
Register::D => &mut self.d,
|
||||||
|
Register::E => &mut self.e,
|
||||||
|
Register::H => &mut self.h,
|
||||||
|
Register::L => &mut self.l,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Flag> for u8 {
|
#[derive(Debug, Copy, Clone)]
|
||||||
fn from(flag: Flag) -> Self {
|
pub enum Register {
|
||||||
flag.0
|
A,
|
||||||
}
|
B,
|
||||||
}
|
C,
|
||||||
|
D,
|
||||||
#[cfg(test)]
|
E,
|
||||||
mod test {
|
H,
|
||||||
use super::*;
|
L,
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn flag_zf_works() {
|
|
||||||
let mut flag: Flag = Default::default();
|
|
||||||
|
|
||||||
flag.set_zf(true);
|
|
||||||
assert_eq!(u8::from(flag), 0b10000000);
|
|
||||||
assert!(flag.get_zf());
|
|
||||||
|
|
||||||
flag.set_zf(false);
|
|
||||||
assert_eq!(u8::from(flag), 0b00000000);
|
|
||||||
assert!(!flag.get_zf());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn flag_n_works() {
|
|
||||||
let mut flag: Flag = Default::default();
|
|
||||||
|
|
||||||
flag.set_n(true);
|
|
||||||
assert_eq!(u8::from(flag), 0b01000000);
|
|
||||||
assert!(flag.get_n());
|
|
||||||
|
|
||||||
flag.set_n(false);
|
|
||||||
assert_eq!(u8::from(flag), 0b00000000);
|
|
||||||
assert!(!flag.get_n());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn flag_h_works() {
|
|
||||||
let mut flag: Flag = Default::default();
|
|
||||||
|
|
||||||
flag.set_h(true);
|
|
||||||
assert_eq!(u8::from(flag), 0b00100000);
|
|
||||||
assert!(flag.get_h());
|
|
||||||
|
|
||||||
flag.set_h(false);
|
|
||||||
assert_eq!(u8::from(flag), 0b00000000);
|
|
||||||
assert!(!flag.get_h());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn flags_work_together() {
|
|
||||||
let mut flag: Flag = Default::default();
|
|
||||||
assert_eq!(u8::from(flag), 0b00000000);
|
|
||||||
|
|
||||||
flag.set_zf(true);
|
|
||||||
flag.set_cy(true);
|
|
||||||
flag.set_h(true);
|
|
||||||
flag.set_n(true);
|
|
||||||
|
|
||||||
assert_eq!(u8::from(flag), 0b11110000);
|
|
||||||
assert!(flag.get_zf());
|
|
||||||
assert!(flag.get_n());
|
|
||||||
assert!(flag.get_h());
|
|
||||||
assert!(flag.get_cy());
|
|
||||||
|
|
||||||
flag.set_cy(false);
|
|
||||||
assert_eq!(u8::from(flag), 0b11100000);
|
|
||||||
assert!(!flag.get_cy());
|
|
||||||
|
|
||||||
flag.set_n(false);
|
|
||||||
assert_eq!(u8::from(flag), 0b10100000);
|
|
||||||
assert!(!flag.get_n());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn flag_to_u8_and_back_works() {
|
|
||||||
let flag: Flag = 0b10011111.into();
|
|
||||||
assert_eq!(u8::from(flag), 0b10010000);
|
|
||||||
assert_eq!(flag.0, 0b10010000);
|
|
||||||
assert!(flag.get_zf());
|
|
||||||
assert!(!flag.get_n());
|
|
||||||
assert!(!flag.get_h());
|
|
||||||
assert!(flag.get_cy());
|
|
||||||
|
|
||||||
let mut base: Flag = Default::default();
|
|
||||||
base.set_h(true);
|
|
||||||
base.set_zf(true);
|
|
||||||
|
|
||||||
assert_eq!(base.0, 0b10100000);
|
|
||||||
assert_eq!(u8::from(base), 0b10100000);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn flag_cy_works() {
|
|
||||||
let mut flag: Flag = Default::default();
|
|
||||||
|
|
||||||
flag.set_cy(true);
|
|
||||||
assert_eq!(u8::from(flag), 0b00010000);
|
|
||||||
assert!(flag.get_cy());
|
|
||||||
|
|
||||||
flag.set_cy(false);
|
|
||||||
assert_eq!(u8::from(flag), 0b00000000);
|
|
||||||
assert!(!flag.get_cy());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn split_u16_works() {
|
|
||||||
let num = 0xABCD;
|
|
||||||
|
|
||||||
let (high, low) = Registers::split_u16(num);
|
|
||||||
assert_eq!(high, 0xAB);
|
|
||||||
assert_eq!(low, 0xCD);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn merge_u8s_works() {
|
|
||||||
let left = 0xAB;
|
|
||||||
let right = 0xCD;
|
|
||||||
|
|
||||||
let res = Registers::merge_u8s(left, right);
|
|
||||||
assert_eq!(res, 0xABCD);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,389 +0,0 @@
|
||||||
use super::cpu::Flag;
|
|
||||||
/// Sharp SM83 Instructions
|
|
||||||
/// ### Definitions
|
|
||||||
/// * "Any valid 8-bit register" refers to the registers `B`, `C`, `D`, `E`, `H` and `L`.
|
|
||||||
/// * If `A` is also a valid register, it will be **explicitly** stated as such.
|
|
||||||
/// * "Any valid 16-bit register" refers to the registers BC, DE and HL.
|
|
||||||
/// * If `AF` is a valid register, it will be **explicitly** stated as such.
|
|
||||||
/// * If `SP` is a valid register, it will be **explicitly** stated as such.
|
|
||||||
/// * the value of any 16-bit register in brackets is the value of the data located at
|
|
||||||
/// the address of the 16-bit register.
|
|
||||||
/// * e.g. the value of `(HL)` would be what is at `memory[cpu.reg.get_hl()]`
|
|
||||||
/// * Since the value is from memory, the value is an 8-bit integer.
|
|
||||||
pub struct Instruction {}
|
|
||||||
|
|
||||||
impl Instruction {
|
|
||||||
// *** 8-bit Loads ***
|
|
||||||
|
|
||||||
/// `LD nn, n` Store value nn in n.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `nn` Any valid 8-bit or 16-bit register (including `SP`).
|
|
||||||
/// * `n` An 8-bit immediate value.
|
|
||||||
pub fn ld_nn_n(nn: u16, n: &mut u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `LD r, r` Store value r2 into r1.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `r1` Any valid 8-bit register (including `A`), and `(HL)`.
|
|
||||||
/// * `r2` Any valid 8-bit register (including `A`), and `(HL)`.
|
|
||||||
pub fn ld_r1_r2(r1: &mut u8, r2: u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `LD A, n` Store value n into register A.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `a` The A register
|
|
||||||
/// * `n` Any valid 8-bit register (including `A`),`(BC)`, `(DE)`, `(HL)`, `(nn)`, and `#`.
|
|
||||||
/// * `nn` A two byte immediate value (Least significant byte first).
|
|
||||||
pub fn ld_a_n(a: &mut u8, n: u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `LD n, A` Store register A into n.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `n` Any valid 8-bit register (including `A`), `(BC)`, `(DE)`, `(HL)`, and `(nn)`.
|
|
||||||
/// * `nn` A two byte immediate value (Least significant byte first).
|
|
||||||
/// * `a` The A register.
|
|
||||||
pub fn ld_n_a(n: &mut u8, a: u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `LD A, (C)` Store value at $FF00 + register C in register A.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `a` The A register.
|
|
||||||
/// * `c` The C register.
|
|
||||||
pub fn ld_a_c(a: &mut u8, c: u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `LD (C) ,A` Store the value of register A into $FF00 + register C.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `c` The C register.
|
|
||||||
/// * `a` The A register.
|
|
||||||
pub fn ld_c_a(c: u8, a: u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
// `LD A, (HLD)` is identical to `LDD A, (HL)`.
|
|
||||||
// `LD A, (HL-)` is identical to `LDD A, (HL)`.
|
|
||||||
|
|
||||||
/// `LDD A, (HL)` Put value at $HL into A, then decrement HL.
|
|
||||||
///
|
|
||||||
/// Identical to `LD A, (HLD)`, and `LD A, (HL-)`.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `a` The A register.
|
|
||||||
/// * `hl` The HL register
|
|
||||||
pub fn ldd_a_hl(a: &mut u8, hl: u16) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
// `LD (HLD), A` is identical to `LDD (HL), A`.
|
|
||||||
// `LD (HL-), A` is identical to `LDD (HL), A`.
|
|
||||||
|
|
||||||
/// `LDD (HL), A` Store register A in $HL, then decrement HL.
|
|
||||||
///
|
|
||||||
/// Identical to `LD (HLD), A`, and `LD (HL-), A`
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `hl` The HL register.
|
|
||||||
/// * `a` The A register.
|
|
||||||
pub fn ldd_hl_a(hl: u16, a: u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
// `LD A, (HLI)` is identical to `LDI A, (HL)`.
|
|
||||||
// `LD A, (HL+)` is identical to `LDI A, (HL)`.
|
|
||||||
|
|
||||||
/// `LDI A, (HL)` Store value at $HL in register A, then increment HL.
|
|
||||||
///
|
|
||||||
/// Identical to `LD A, (HLI)`, and `LD A, (HL+)`.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `a` The A register.
|
|
||||||
/// * `hl` The HL register.
|
|
||||||
pub fn ldi_a_hl(a: &mut u8, hl: u16) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
// `LD (HLI), A` is identical to `LDI (HL), A`.
|
|
||||||
// `LD (HL+), A` is identical to `LDI (HL), A`.
|
|
||||||
|
|
||||||
/// `LDI (HL), A` Store register A in $HL, then increment HL.
|
|
||||||
///
|
|
||||||
/// Identical to `LD (HLI), A`, and `LD (HL+), A`.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `hl` The HL register.
|
|
||||||
/// * `a` The A register.
|
|
||||||
pub fn ldi_hl_a(hl: u16, a: u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `LDH (n), A` Store register A into address $FF00 + n.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `n` An 8-bit immediate value.
|
|
||||||
/// * `a` The A register.
|
|
||||||
pub fn ldh_n_a(n: u8, a: u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `LDH A, (n)` Store address $FF00 + n in the A register.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `a` The A register.
|
|
||||||
/// * `n` An 8-bit immediate value
|
|
||||||
pub fn ldh_a_n(a: &mut u8, n: u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** 16-bit Loads ***
|
|
||||||
|
|
||||||
/// `LD n, nn` Store value nn in n.(really?)
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `n` Any 16-bit register (including `SP`).
|
|
||||||
/// * `nn` A 16-bit immediate value.
|
|
||||||
pub fn ld_n_nn(n: &mut u16, nn: u16) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `LD SP, HL` Put HL into the stack pointer.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `sp` The stack pointer register.
|
|
||||||
/// * `hl` The HL register.
|
|
||||||
pub fn ld_sp_hl(sp: &mut u16, hl: u16) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
// `LD HL, SP + n` is identical to `LDHL SP, n`.
|
|
||||||
|
|
||||||
/// `LDHL SP, n` "Put SP + n effective address into HL".
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `hl` The HL register.
|
|
||||||
/// * `sp` The stack pointer register.
|
|
||||||
/// * `n` 8-bit **signed** integer.
|
|
||||||
/// * `f` CPU flags.
|
|
||||||
///
|
|
||||||
/// ### Flags
|
|
||||||
/// * `ZF` Reset.
|
|
||||||
/// * `N` Reset.
|
|
||||||
/// * `H` Set / Reset depending on operation.
|
|
||||||
/// * `CY` Set / Reset depending on operation.
|
|
||||||
pub fn ldhl_sp_n(hl: &mut u16, sp: u16, n: i8, f: &mut Flag) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `LD (nn), SP` Store stack pointer at $nn.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `nn` A 16-bit immediate address.
|
|
||||||
/// * `sp` The stack pointer register.
|
|
||||||
pub fn ld_nn_sp(nn: u16, sp: u16) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `PUSH nn` Push 16-bit register onto the stack, then
|
|
||||||
/// decrement the stack pointer twice.
|
|
||||||
/// ### Arguments
|
|
||||||
/// * `nn` Any valid 16-bit address (including `AF`).
|
|
||||||
/// * `sp` The stack pointer register.
|
|
||||||
/// * `stack` The stack.
|
|
||||||
pub fn push_nn(nn: u16, sp: &mut u16, stack: &[u16]) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `POP nn` Pop two bytes of the stack into register pair nn,
|
|
||||||
/// then increment the stack pointer twice.
|
|
||||||
/// ### Arguments
|
|
||||||
/// `nn` Any valid 16-bit address (including `AF`).
|
|
||||||
/// `sp` The stack pointer register.
|
|
||||||
/// `stack` The stack.
|
|
||||||
pub fn pop_nn(nn: &mut u16, sp: &mut u16, stack: &[u16]) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** 8-bit ALU ***
|
|
||||||
|
|
||||||
/// `ADD A, n` Add n to register A.
|
|
||||||
/// ### Arguments
|
|
||||||
/// `A` The A register
|
|
||||||
/// `nn` Any valid 8-bit register (including `A`), `(HL)`, and `#`.
|
|
||||||
///
|
|
||||||
/// ### Flags
|
|
||||||
/// `ZF` Set if result is zero..
|
|
||||||
/// `N` Reset.
|
|
||||||
/// `H` Set if carry from bit 3.
|
|
||||||
/// `CY` Set if carry from bit 7.
|
|
||||||
pub fn add_a_n(a: &mut u8, n: u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `ADC A, n` Add n + carry flag to register A.
|
|
||||||
/// ### Arguments
|
|
||||||
/// `A` The A register.
|
|
||||||
/// `n` Any valid 8-bit register (including `A`), `(HL)`, and `#`.
|
|
||||||
///
|
|
||||||
/// ### Flags
|
|
||||||
/// `ZF` Set if result is zero.
|
|
||||||
/// `N` Reset.
|
|
||||||
/// `H` Set if carry from bit 3.
|
|
||||||
/// `CY` Set if carry from bit 7.
|
|
||||||
pub fn adc_a_n(a: &mut u8, n: u8, f: &mut Flag) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `SUB n` or `SUB A, n` Subtract n from register A.
|
|
||||||
/// ### Arguments
|
|
||||||
/// `A` The A register.
|
|
||||||
/// `n` Any valid 8-bit register (including `A`), `(HL)`, and `#`.
|
|
||||||
///
|
|
||||||
/// ### Flags
|
|
||||||
/// `ZF` Set if result is 0.
|
|
||||||
/// `N` Set.
|
|
||||||
/// `H` Set if no borrow from bit 4.
|
|
||||||
/// `CY` Set if no borrow.
|
|
||||||
pub fn sub_a_n(a: &mut u8, n: u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `SBC A, n` Subtract n + carry flag from register A.
|
|
||||||
/// ### Arguments
|
|
||||||
/// `A` The A register.
|
|
||||||
/// `n` Any valid 8-bit register (including `A`), `(HL)`, and `#`.
|
|
||||||
///
|
|
||||||
/// ### Flags
|
|
||||||
/// `ZF` Set if result is 0.
|
|
||||||
/// `N` Set.
|
|
||||||
/// `H` Set if no borrow from bit 4.
|
|
||||||
/// `CY` Set if no borrow.
|
|
||||||
pub fn sbc_a_n(a: &mut u8, n: u8, f: &mut Flag) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `AND n` or `AND A, n` AND n with register A,
|
|
||||||
/// then store the result in register A.
|
|
||||||
/// ### Arguments
|
|
||||||
/// `A` The A register.
|
|
||||||
/// `n` Any valid 8-bit register (including `A`), `(HL)`, and `#`.
|
|
||||||
///
|
|
||||||
/// ### Flags
|
|
||||||
/// `ZF` Set if result is zero.
|
|
||||||
/// `N` Reset
|
|
||||||
/// `H` Set
|
|
||||||
/// `CY` Reset
|
|
||||||
pub fn and_a_n(a: &mut u8, n: u8, f: &mut Flag) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `OR n` or `OR A, n` OR n with register A, then store the result in register A
|
|
||||||
/// ### Arguments
|
|
||||||
/// `A` The A register.
|
|
||||||
/// `n` Any valid 8-bit register (including `A`), `(HL)`, and `#`.
|
|
||||||
///
|
|
||||||
/// ### Flags
|
|
||||||
/// `ZF` Set if result is zero.
|
|
||||||
/// `N` Reset.
|
|
||||||
/// `H` Reset.
|
|
||||||
/// `CY` Reset.
|
|
||||||
pub fn or_a_n(a: &mut u8, n: u8, f: &mut Flag) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `XOR n` or `XOR A, n` XOR n with register A, then store the result in register A.
|
|
||||||
/// ### Arguments
|
|
||||||
/// `A` The A register.
|
|
||||||
/// `n` Any valid -bit register (including `A`), `(HL)`, and `#`.
|
|
||||||
///
|
|
||||||
/// ### Flags
|
|
||||||
/// `ZF` Set if result is zero.
|
|
||||||
/// `N` Reset.
|
|
||||||
/// `H` Reset.
|
|
||||||
/// `CY` Reset.
|
|
||||||
pub fn xor_a_n(a: &mut u8, n: u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `CP n` or `CP A, n` Compare register A with n.
|
|
||||||
///
|
|
||||||
/// Note: This is equivalent with `SUB A, n` except that the result of the
|
|
||||||
/// subtraction is discarded. Only the flags are mutated.
|
|
||||||
/// ### Arguments
|
|
||||||
/// `A` The A register.
|
|
||||||
/// `n` Any valid 8-bit register (including `A`), `(HL)`, and `#`.
|
|
||||||
///
|
|
||||||
/// ### Flags
|
|
||||||
/// `ZF` Set if result is zero ( A == n ).
|
|
||||||
/// `N` Set.
|
|
||||||
/// `H` Set if no borrow from bit 4.
|
|
||||||
/// `CY` Set for no borrow. ( A < n ).
|
|
||||||
pub fn cp_a_n(a: u8, n: u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `INC n` Increment register n.
|
|
||||||
/// ### Arguments
|
|
||||||
/// `n` Any valid 8-bit register (including `A`), and `(HL)`.
|
|
||||||
///
|
|
||||||
/// ### Flags
|
|
||||||
/// `ZF` Set if result is zero.
|
|
||||||
/// `N` Reset.
|
|
||||||
/// `H` Set if carry from bit 3.
|
|
||||||
/// `CY` Not affected.
|
|
||||||
pub fn inc_n(n: &mut u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `DEC n` decrement register n.
|
|
||||||
/// ### Arguments
|
|
||||||
/// `n` Any 8-bit register (including `A`), and `(HL)`.
|
|
||||||
///
|
|
||||||
/// ### Flags
|
|
||||||
/// `ZF` Set if result is zero.
|
|
||||||
/// `N` Set.
|
|
||||||
/// `H` Set if no borrow from bit 4.
|
|
||||||
/// `CY` Not affected.
|
|
||||||
pub fn dec_n(n: &mut u8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** 16-bit Arithmetic ***
|
|
||||||
|
|
||||||
/// `ADD HL, n` Add n to HL.
|
|
||||||
/// ### Arguments
|
|
||||||
/// `hl` The HL register.
|
|
||||||
/// `n` Any valid 16-bit address (including `SP`).
|
|
||||||
///
|
|
||||||
/// ### Flags
|
|
||||||
/// `ZF` Not affected
|
|
||||||
/// `N` Reset
|
|
||||||
/// `H` Set if carry from bit 11.
|
|
||||||
/// `CY` Set if carry from bit 15.
|
|
||||||
pub fn add_hl_n(hl: &mut u16, n: u16) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `ADD SP, n` Add n to the stack pointer.
|
|
||||||
/// ### Arguments
|
|
||||||
/// `sp` The stack pointer register.
|
|
||||||
/// `n` AN 8-bit signed immediate value (#).
|
|
||||||
///
|
|
||||||
/// ### Flags
|
|
||||||
/// `ZF` Reset
|
|
||||||
/// `N` Reset
|
|
||||||
/// `H` Set or reset according to operation.
|
|
||||||
/// `CY` Set or reset according to operation.
|
|
||||||
pub fn add_sp_n(sp: &mut u16, n: i8) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `INC nn` Increment register nn
|
|
||||||
/// ### Arguments
|
|
||||||
/// `nn` Any valid 16-bit register (including `SP`)
|
|
||||||
pub fn inc_nn(nn: &mut u16) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `DEC nn` Increment register nn
|
|
||||||
/// ### Arguments
|
|
||||||
/// `nn` Any valid 16-bit register (including `SP`)
|
|
||||||
pub fn dec_nn(nn: &mut u16) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** Miscellaneous ***
|
|
||||||
}
|
|
|
@ -1,2 +1,4 @@
|
||||||
|
pub use cpu::LR35902;
|
||||||
|
|
||||||
|
pub mod bus;
|
||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
pub mod instructions;
|
|
||||||
|
|
Loading…
Reference in New Issue