mirror of
https://github.com/FranLMSP/rmg-001.git
synced 2024-11-23 10:12:11 +00:00
JP u16 instruction
This commit is contained in:
parent
5d04b7c346
commit
92229e3d93
@ -1,3 +1,5 @@
|
|||||||
|
use std::{thread, time};
|
||||||
|
|
||||||
use crate::cpu::CPU;
|
use crate::cpu::CPU;
|
||||||
use crate::ppu::PPU;
|
use crate::ppu::PPU;
|
||||||
use crate::bus::Bus;
|
use crate::bus::Bus;
|
||||||
@ -18,6 +20,11 @@ impl Console {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn cpu_run(&mut self) {
|
pub fn cpu_run(&mut self) {
|
||||||
self.cpu.run(&mut self.bus);
|
let mut exit = false;
|
||||||
|
while !exit {
|
||||||
|
self.cpu.run(&mut self.bus);
|
||||||
|
|
||||||
|
thread::sleep(time::Duration::from_millis(100));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
48
src/cpu.rs
48
src/cpu.rs
@ -1,6 +1,7 @@
|
|||||||
use crate::utils::{BitIndex, get_bit, set_bit};
|
use crate::utils::{BitIndex, get_bit, set_bit, join_bytes};
|
||||||
use crate::bus::Bus;
|
use crate::bus::Bus;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum Register {
|
pub enum Register {
|
||||||
A(u8), // Accumulator
|
A(u8), // Accumulator
|
||||||
F(u8), // Flags
|
F(u8), // Flags
|
||||||
@ -20,6 +21,7 @@ pub enum Register {
|
|||||||
PC(u16), // Program counter
|
PC(u16), // Program counter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum FlagRegister {
|
pub enum FlagRegister {
|
||||||
Zero(bool), // Set when the result of a math operation is zero or if two values matches using the CP instruction
|
Zero(bool), // Set when the result of a math operation is zero or if two values matches using the CP instruction
|
||||||
Substract(bool), // Set if a substraction was performed in the last math instruction
|
Substract(bool), // Set if a substraction was performed in the last math instruction
|
||||||
@ -117,19 +119,19 @@ impl Registers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_af(&self) -> u16 {
|
fn get_af(&self) -> u16 {
|
||||||
((self.a as u16) << 8) | (self.f as u16)
|
join_bytes(self.a, self.f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_bc(&self) -> u16 {
|
fn get_bc(&self) -> u16 {
|
||||||
((self.b as u16) << 8) | (self.c as u16)
|
join_bytes(self.b, self.c)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_de(&self) -> u16 {
|
fn get_de(&self) -> u16 {
|
||||||
((self.d as u16) << 8) | (self.e as u16)
|
join_bytes(self.d, self.e)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_hl(&self) -> u16 {
|
fn get_hl(&self) -> u16 {
|
||||||
((self.h as u16) << 8) | (self.l as u16)
|
join_bytes(self.h, self.l)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_af(&mut self, val: u16) {
|
fn set_af(&mut self, val: u16) {
|
||||||
@ -157,6 +159,7 @@ impl Registers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum OpcodeParameter {
|
pub enum OpcodeParameter {
|
||||||
Register(Register),
|
Register(Register),
|
||||||
Register_U8(Register),
|
Register_U8(Register),
|
||||||
@ -197,6 +200,7 @@ pub enum OpcodeParameter {
|
|||||||
NoParam,
|
NoParam,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum CpuOpcode {
|
pub enum CpuOpcode {
|
||||||
LD(OpcodeParameter),
|
LD(OpcodeParameter),
|
||||||
LDD(OpcodeParameter),
|
LDD(OpcodeParameter),
|
||||||
@ -266,17 +270,35 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self, bus: &mut Bus) {
|
pub fn run(&mut self, bus: &mut Bus) {
|
||||||
println!("Opcode: {:02X}", bus.read(self.registers.get(Register::PC(0))));
|
let program_counter = self.registers.get(Register::PC(0));
|
||||||
|
let byte_read = bus.read(program_counter);
|
||||||
|
let opcode = CPU::parse_opcode(byte_read, program_counter, bus);
|
||||||
|
self.exec(opcode, bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exec(&mut self, opcode: CpuOpcode) {
|
pub fn exec(&mut self, opcode: CpuOpcode, bus: &mut Bus) {
|
||||||
|
println!("Executing {:?}", opcode);
|
||||||
|
println!("Current PC{:?}", self.registers.get(Register::PC(0)));
|
||||||
match opcode {
|
match opcode {
|
||||||
|
CpuOpcode::JP(params) => match params {
|
||||||
|
OpcodeParameter::U16(address) => self.registers.set(Register::PC(address)),
|
||||||
|
_ => {},
|
||||||
|
},
|
||||||
CpuOpcode::NOP => self.registers.increment_pc(),
|
CpuOpcode::NOP => self.registers.increment_pc(),
|
||||||
_ => println!("Illegal instruction"),
|
_ => println!("Illegal instruction"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_opcode(opcode: u8) -> CpuOpcode {
|
fn read_parameter_bytes(address: u16, bus: &Bus) -> [u8; 3] {
|
||||||
|
[
|
||||||
|
bus.read(address),
|
||||||
|
bus.read(address + 1),
|
||||||
|
bus.read(address + 2),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_opcode(opcode: u8, address: u16, bus: &Bus) -> CpuOpcode {
|
||||||
|
let params = CPU::read_parameter_bytes(address, &bus);
|
||||||
match opcode {
|
match opcode {
|
||||||
0x06 => CpuOpcode::LD(OpcodeParameter::Register_U8(Register::B(0))),
|
0x06 => CpuOpcode::LD(OpcodeParameter::Register_U8(Register::B(0))),
|
||||||
0x0E => CpuOpcode::LD(OpcodeParameter::Register_U8(Register::C(0))),
|
0x0E => CpuOpcode::LD(OpcodeParameter::Register_U8(Register::C(0))),
|
||||||
@ -499,7 +521,7 @@ impl CPU {
|
|||||||
//0xCB => CpuOpcode::BIT,
|
//0xCB => CpuOpcode::BIT,
|
||||||
//0xCB => CpuOpcode::SET,
|
//0xCB => CpuOpcode::SET,
|
||||||
//0xCB => CpuOpcode::RES,
|
//0xCB => CpuOpcode::RES,
|
||||||
0xC3 => CpuOpcode::JP(OpcodeParameter::U16(0)),
|
0xC3 => CpuOpcode::JP(OpcodeParameter::U16(join_bytes(params[1], params[2]))),
|
||||||
0xC2 => CpuOpcode::JP(OpcodeParameter::FlagRegisterReset_U16(FlagRegister::Zero(true), 0)),
|
0xC2 => CpuOpcode::JP(OpcodeParameter::FlagRegisterReset_U16(FlagRegister::Zero(true), 0)),
|
||||||
0xCA => CpuOpcode::JP(OpcodeParameter::FlagRegisterSet_U16(FlagRegister::Zero(true), 0)),
|
0xCA => CpuOpcode::JP(OpcodeParameter::FlagRegisterSet_U16(FlagRegister::Zero(true), 0)),
|
||||||
0xD2 => CpuOpcode::JP(OpcodeParameter::FlagRegisterReset_U16(FlagRegister::Carry(true), 0)),
|
0xD2 => CpuOpcode::JP(OpcodeParameter::FlagRegisterReset_U16(FlagRegister::Carry(true), 0)),
|
||||||
@ -600,7 +622,13 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_cpu_instructions() {
|
fn test_cpu_instructions() {
|
||||||
let mut cpu = CPU::new();
|
let mut cpu = CPU::new();
|
||||||
cpu.exec(CpuOpcode::NOP);
|
let mut bus = Bus::new();
|
||||||
|
cpu.exec(CpuOpcode::NOP, &mut bus);
|
||||||
assert_eq!(cpu.registers.get(Register::PC(0)), 0x101);
|
assert_eq!(cpu.registers.get(Register::PC(0)), 0x101);
|
||||||
|
|
||||||
|
let mut cpu = CPU::new();
|
||||||
|
let mut bus = Bus::new();
|
||||||
|
cpu.exec(CpuOpcode::JP(OpcodeParameter::U16(0x1F1F)), &mut bus);
|
||||||
|
assert_eq!(cpu.registers.get(Register::PC(0)), 0x1F1F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
src/utils.rs
10
src/utils.rs
@ -33,6 +33,10 @@ pub fn set_bit(byte: u8, value: bool, index: BitIndex) -> u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn join_bytes(byte1: u8, byte2: u8) -> u16 {
|
||||||
|
((byte1 as u16) << 8) | (byte2 as u16)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -84,4 +88,10 @@ mod tests {
|
|||||||
assert_eq!(get_bit(0b10111111, BitIndex::I6), false);
|
assert_eq!(get_bit(0b10111111, BitIndex::I6), false);
|
||||||
assert_eq!(get_bit(0b01111111, BitIndex::I7), false);
|
assert_eq!(get_bit(0b01111111, BitIndex::I7), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_join_two_bytes() {
|
||||||
|
assert_eq!(join_bytes(0b10101010, 0b11111111), 0b1010101011111111);
|
||||||
|
assert_eq!(join_bytes(0b11111111, 0b10101010), 0b1111111110101010);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user