feat: implement more registers
This commit is contained in:
parent
70de3b9142
commit
c0b8b8bda2
|
@ -1,4 +1,5 @@
|
||||||
use super::cartridge::Cartridge;
|
use super::cartridge::Cartridge;
|
||||||
|
use super::high_ram::HighRAM;
|
||||||
use super::interrupt::Interrupt;
|
use super::interrupt::Interrupt;
|
||||||
use super::ppu::PPU;
|
use super::ppu::PPU;
|
||||||
use super::sound::Sound;
|
use super::sound::Sound;
|
||||||
|
@ -15,6 +16,7 @@ pub struct Bus {
|
||||||
timer: Timer,
|
timer: Timer,
|
||||||
interrupt: Interrupt,
|
interrupt: Interrupt,
|
||||||
sound: Sound,
|
sound: Sound,
|
||||||
|
hram: HighRAM,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Bus {
|
impl Default for Bus {
|
||||||
|
@ -28,6 +30,7 @@ impl Default for Bus {
|
||||||
timer: Default::default(),
|
timer: Default::default(),
|
||||||
interrupt: Default::default(),
|
interrupt: Default::default(),
|
||||||
sound: Default::default(),
|
sound: Default::default(),
|
||||||
|
hram: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,7 +114,7 @@ impl Bus {
|
||||||
}
|
}
|
||||||
0xFF80..=0xFFFE => {
|
0xFF80..=0xFFFE => {
|
||||||
// High RAM
|
// High RAM
|
||||||
unimplemented!("Unable to read {:#06X} in High RAM", addr);
|
self.hram.read_byte((addr - 0xFF80) as usize)
|
||||||
}
|
}
|
||||||
0xFFFF => {
|
0xFFFF => {
|
||||||
// Interupts Enable Register
|
// Interupts Enable Register
|
||||||
|
@ -175,7 +178,7 @@ impl Bus {
|
||||||
}
|
}
|
||||||
0xFF80..=0xFFFE => {
|
0xFF80..=0xFFFE => {
|
||||||
// High RAM
|
// High RAM
|
||||||
unimplemented!("Unable to write to {:#06X} in High RAM", addr);
|
self.hram.write_byte((addr - 0xFF80) as usize, byte);
|
||||||
}
|
}
|
||||||
0xFFFF => {
|
0xFFFF => {
|
||||||
// Interupts Enable Register
|
// Interupts Enable Register
|
||||||
|
|
70
src/cpu.rs
70
src/cpu.rs
|
@ -1,5 +1,6 @@
|
||||||
use super::bus::Bus;
|
use super::bus::Bus;
|
||||||
use super::instruction::Instruction;
|
use super::instruction::Instruction;
|
||||||
|
use std::fmt::{Display, Formatter, Result as FmtResult};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct Cpu {
|
pub struct Cpu {
|
||||||
|
@ -60,7 +61,28 @@ impl Cpu {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode(&mut self, opcode: u8) -> Instruction {
|
pub fn decode(&mut self, opcode: u8) -> Instruction {
|
||||||
Instruction::from_byte(self, opcode)
|
let tmp = Instruction::from_byte(self, opcode);
|
||||||
|
|
||||||
|
let a = self.register(Register::A);
|
||||||
|
let flag: Flags = self.register(Register::Flag).into();
|
||||||
|
let bc = self.register_pair(RegisterPair::BC);
|
||||||
|
let de = self.register_pair(RegisterPair::DE);
|
||||||
|
let hl = self.register_pair(RegisterPair::HL);
|
||||||
|
let sp = self.register_pair(RegisterPair::SP);
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"A: {:#04X} | BC: {:#06X} | DE: {:#06X} | HL: {:#06X} | SP: {:#06X} | {}",
|
||||||
|
a, bc, de, hl, sp, flag
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get info from serial port
|
||||||
|
// if self.bus.read_byte(0xFF02) == 0x81 {
|
||||||
|
// let c = self.bus.read_byte(0xFF01) as char;
|
||||||
|
// self.bus.write_byte(0xFF02, 0x00);
|
||||||
|
// print!("TEST RESULT!: {}", c);
|
||||||
|
// }
|
||||||
|
|
||||||
|
tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(&mut self, instruction: Instruction) {
|
pub fn execute(&mut self, instruction: Instruction) {
|
||||||
|
@ -68,6 +90,24 @@ impl Cpu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Cpu {
|
||||||
|
pub fn dbg_read_byte(&self, addr: u16) -> u8 {
|
||||||
|
self.bus.read_byte(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dbg_write_byte(&mut self, addr: u16, byte: u8) {
|
||||||
|
self.bus.write_byte(addr, byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dbg_read_word(&self, addr: u16) -> u16 {
|
||||||
|
self.bus.read_word(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dbg_write_word(&mut self, addr: u16, word: u16) {
|
||||||
|
self.bus.write_word(addr, word)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Cpu {
|
impl Cpu {
|
||||||
pub fn read_byte(&mut self, addr: u16) -> u8 {
|
pub fn read_byte(&mut self, addr: u16) -> u8 {
|
||||||
let byte = self.bus.read_byte(addr);
|
let byte = self.bus.read_byte(addr);
|
||||||
|
@ -223,6 +263,34 @@ impl Flags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Flags {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
if self.z {
|
||||||
|
f.write_str("Z")?;
|
||||||
|
} else {
|
||||||
|
f.write_str("_")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.n {
|
||||||
|
f.write_str("N")?;
|
||||||
|
} else {
|
||||||
|
f.write_str("_")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.h {
|
||||||
|
f.write_str("H")?;
|
||||||
|
} else {
|
||||||
|
f.write_str("_")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.c {
|
||||||
|
f.write_str("C")
|
||||||
|
} else {
|
||||||
|
f.write_str("_")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<u8> for Flags {
|
impl From<u8> for Flags {
|
||||||
fn from(flag: u8) -> Self {
|
fn from(flag: u8) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct HighRAM {
|
||||||
|
buf: Box<[u8]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for HighRAM {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
buf: vec![0u8; 127].into_boxed_slice(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HighRAM {
|
||||||
|
pub fn write_byte(&mut self, index: usize, byte: u8) {
|
||||||
|
self.buf[index] = byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_byte(&self, index: usize) -> u8 {
|
||||||
|
self.buf[index]
|
||||||
|
}
|
||||||
|
}
|
|
@ -1509,10 +1509,12 @@ impl Instruction {
|
||||||
fn push(cpu: &mut Cpu, value: u16) {
|
fn push(cpu: &mut Cpu, value: u16) {
|
||||||
let mut sp = cpu.register_pair(RegisterPair::SP);
|
let mut sp = cpu.register_pair(RegisterPair::SP);
|
||||||
|
|
||||||
|
// FIXME: Are these debug functions really necessary?
|
||||||
|
|
||||||
sp -= 1;
|
sp -= 1;
|
||||||
cpu.write_byte(sp, (value >> 8) as u8);
|
cpu.dbg_write_byte(sp, (value >> 8) as u8);
|
||||||
sp -= 1;
|
sp -= 1;
|
||||||
cpu.write_byte(sp, value as u8);
|
cpu.dbg_write_byte(sp, value as u8);
|
||||||
|
|
||||||
cpu.set_register_pair(RegisterPair::SP, sp);
|
cpu.set_register_pair(RegisterPair::SP, sp);
|
||||||
}
|
}
|
||||||
|
@ -1523,9 +1525,11 @@ impl Instruction {
|
||||||
fn pop(cpu: &mut Cpu) -> u16 {
|
fn pop(cpu: &mut Cpu) -> u16 {
|
||||||
let mut sp = cpu.register_pair(RegisterPair::SP);
|
let mut sp = cpu.register_pair(RegisterPair::SP);
|
||||||
|
|
||||||
let low = cpu.read_byte(sp);
|
// FIXME: Are these debug functions really necessary?
|
||||||
|
|
||||||
|
let low = cpu.dbg_read_byte(sp);
|
||||||
sp += 1;
|
sp += 1;
|
||||||
let high = cpu.read_byte(sp);
|
let high = cpu.dbg_read_byte(sp);
|
||||||
sp += 1;
|
sp += 1;
|
||||||
|
|
||||||
cpu.set_register_pair(RegisterPair::SP, sp);
|
cpu.set_register_pair(RegisterPair::SP, sp);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
mod bus;
|
mod bus;
|
||||||
mod cartridge;
|
mod cartridge;
|
||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
|
mod high_ram;
|
||||||
mod instruction;
|
mod instruction;
|
||||||
mod interrupt;
|
mod interrupt;
|
||||||
mod ppu;
|
mod ppu;
|
||||||
|
|
|
@ -11,7 +11,7 @@ fn main() {
|
||||||
let instruction = game_boy.decode(opcode);
|
let instruction = game_boy.decode(opcode);
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"Addr: {:#06X} | Opcode: {:#04X} | Instr: {:X?}",
|
"\nAddr: {:#06X} | Opcode: {:#04X} | Instr: {:X?}",
|
||||||
pc, opcode, instruction
|
pc, opcode, instruction
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue