FDXF3GQNDC2QFZDM55EG4HLP74ZF5T6XGCO2L7ELN2WIIZEB5PUAC #![no_std]mod gbcore;pub use gbcore::*;mod helpers;
use core::convert::TryInto;#[derive(PartialEq, Eq, Clone, Debug)]pub(crate) struct Splitu16(u16);impl From<u16> for Splitu16 {fn from(f: u16) -> Self {let mut result = Splitu16::new();result.set_u16(f);result}}impl Splitu16 {pub(crate) const fn new() -> Splitu16 {Splitu16(0)}pub(crate) const fn as_u16(&self) -> u16 {self.0}pub(crate) fn set_u16(&mut self, f: u16) -> &mut Splitu16 {self.0 = f;self}pub(crate) fn high_u8(&self) -> u8 {(self.0 >> 8).try_into().unwrap()}pub(crate) fn set_high_u8(&mut self, f: u8) {self.0 |= u16::from(f) << 8}pub(crate) fn low_u8(&self) -> u8 {(self.0 & 0x0F).try_into().unwrap()}pub(crate) fn set_low_u8(&mut self, f: u8) {self.0 |= u16::from(f)}}#[cfg(test)]mod tests {use super::*;#[test]fn splitu16() {let expected = Splitu16(0b1111111100000000);let mut real = Splitu16::new();real.set_high_u8(0xFF);assert_eq!(expected, real);let expected = Splitu16(0b0000000011111111);let mut real = Splitu16::new();real.set_low_u8(0xFF);assert_eq!(expected, real);}}
use core::panic;use log::error;use super::helpers::Splitu16;#[cfg(test)]mod tests {#[allow(unused_imports)]use super::*;}#[derive(PartialEq, Eq, Clone, Debug)]pub struct GbCore<'rom> {cpu: Cpu,memory: Memory<8, 8>,screen: Screen,rom: Option<&'rom [u8]>,}#[derive(PartialEq, Eq, Clone, Debug)]struct Screen;#[derive(PartialEq, Eq, Clone, Debug)]struct Cpu {registers: Registers,}#[derive(PartialEq, Eq, Clone, Debug)]struct Memory<const W: usize, const V: usize> {wram: [u8; W],vram: [u8; V],}impl<const W: usize, const V: usize> Default for Memory<W, V> {fn default() -> Self {Memory::<W, V> {wram: [0x0; W],vram: [0x0; V],}}}#[allow(non_snake_case)]#[derive(PartialEq, Eq, Clone, Debug)]struct Registers {AF: Splitu16,BC: Splitu16,DE: Splitu16,HL: Splitu16,SP: u16,PC: u16,}impl<'rom> GbCore<'rom> {pub fn new() -> GbCore<'rom> {GbCore {cpu: Cpu {registers: Registers {AF: Splitu16::from(0x01B0),BC: Splitu16::from(0x0013),DE: Splitu16::from(0x00D8),HL: Splitu16::from(0x014D),SP: 0xFFFE,PC: 0x0100,}},memory: Memory::<8, 8>::default(),screen: Screen,rom: None,}}pub fn load(&mut self, rom: &'rom [u8]) -> &mut GbCore<'rom> {self.rom = Some(rom);self}pub fn fetch(&self) -> u8 {debug_assert!(self.rom.is_some());self.rom.unwrap()[usize::from(self.cpu.registers.PC)]}pub fn fetch_op(&mut self) -> TranslatedOpCode {match self.fetch() {0x0 => TranslatedOpCode::Noop,0xC3 => {let mut address = u16::from(self.next().fetch()) << 8;address |= u16::from(self.next().fetch());TranslatedOpCode::Jmp(address)}e => {error!("Unknown Op Code {:#X}", e);panic!();}}}pub fn next(&mut self) -> &mut GbCore<'rom> {self.cpu.registers.PC += 1;self}pub fn test(self, x: i32) {log::error!("Oh dear, x is '{}'", x);}}impl Default for GbCore<'_> {fn default() -> Self {Self::new()}}#[derive(Clone, Debug)]pub enum TranslatedOpCode {Noop,Jmp(u16),}
[package]name = "gbcore"version = "0.1.0"authors = ["Daniel Stroh <strohdaniel624@gmail.com>"]edition = "2018"# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[dependencies]log = "0.4"
use std::{fs::File, io::Read};fn main() {env_logger::init();let rom: Vec<u8> = File::open("testroms/cpu_instrs.gb").expect("Cannot open file.").bytes().filter_map(|x| x.ok()).collect();let mut x = gbcore::GbCore::new();x.load(&rom);for i in 1..100 {println!("Op {}: {:#X?}", i, x.fetch_op());x.next();}x.test(13);println!("Hello, world!");}
[package]name = "emu"version = "0.1.0"authors = ["Daniel Stroh <strohdaniel624@gmail.com>"]edition = "2018"# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[dependencies]gbcore = {path = "../gbcore" }env_logger = "0.8"
[workspace]members = ["gbcore","emu",]