i just keep getting better huh

This commit is contained in:
Alex Janka 2023-09-10 10:56:21 +10:00
parent f4f97982ce
commit b19940b88e
7 changed files with 170 additions and 171 deletions

View file

@ -58,8 +58,11 @@ pub struct GameboyEmu {
params: Arc<EmuParams>,
}
type FrameReceiver = Mutex<Option<Receiver<Vec<[u8; 4]>>>>;
type JoypadSender = Mutex<Option<Sender<(JoypadButtons, bool)>>>;
type Frame = Vec<[u8; 4]>;
type JoypadInfo = (JoypadButtons, bool);
type FrameReceiver = Mutex<Option<Receiver<Frame>>>;
type JoypadSender = Mutex<Option<Sender<JoypadInfo>>>;
const BUFFERS_PER_FRAME: usize = 1;
const DOWNSAMPLE_TYPE: DownsampleType = DownsampleType::Linear;

View file

@ -14,7 +14,7 @@ use keyboard_types::{Code, KeyState};
use nih_plug::prelude::*;
use pixels::{wgpu::PowerPreference, Pixels, SurfaceTexture};
use crate::{FrameReceiver, JoypadSender};
use crate::{Frame, FrameReceiver, JoypadInfo, JoypadSender};
pub struct Emulator {
frame_receiver: Arc<FrameReceiver>,
@ -89,7 +89,7 @@ impl Editor for Emulator {
pub struct EmulatorWindow {
pix: Pixels,
scale: usize,
scaled_buf: Vec<[u8; 4]>,
scaled_buf: Frame,
frame_receiver: Arc<FrameReceiver>,
joypad_sender: Arc<JoypadSender>,
}
@ -117,7 +117,7 @@ impl EmulatorWindow {
}
}
fn init_pixbuf(info: WindowInfo, window: &mut Window) -> (Pixels, usize, Vec<[u8; 4]>) {
fn init_pixbuf(info: WindowInfo, window: &mut Window) -> (Pixels, usize, Frame) {
let physical_size = info.physical_size();
let scale = (physical_size.width as usize / WIDTH).min(physical_size.height as usize / HEIGHT);
let scaled_buf = vec![[0, 0, 0, 0xFF]; WIDTH * scale * HEIGHT * scale];
@ -194,16 +194,15 @@ impl WindowHandler for EmulatorWindow {
}
pub struct EmulatorRenderer {
tx: Sender<Vec<[u8; 4]>>,
tx: Sender<Frame>,
joypad: JoypadState,
keys: Receiver<(JoypadButtons, bool)>,
keys: Receiver<JoypadInfo>,
}
impl EmulatorRenderer {
#[allow(clippy::type_complexity)]
pub(super) fn new() -> (Self, Receiver<Vec<[u8; 4]>>, Sender<(JoypadButtons, bool)>) {
let (tx, rx) = mpsc::channel::<Vec<[u8; 4]>>();
let (keys_tx, keys) = mpsc::channel::<(JoypadButtons, bool)>();
pub(super) fn new() -> (Self, Receiver<Frame>, Sender<JoypadInfo>) {
let (tx, rx) = mpsc::channel::<Frame>();
let (keys_tx, keys) = mpsc::channel::<JoypadInfo>();
(
Self {
tx,

View file

@ -1,152 +0,0 @@
use crate::{
connect::{PocketCamera, Renderer},
processor::{memory::mmio::gpu::Colour, Cpu, Direction, Flags, Reg8, SplitRegister},
util::{clear_bit, get_bit, set_bit},
};
impl<ColourFormat, R, C> Cpu<ColourFormat, R, C>
where
ColourFormat: From<Colour> + Copy,
R: Renderer<ColourFormat>,
C: PocketCamera + Send + 'static,
{
pub(crate) fn and(&mut self, first: u8, second: u8) -> u8 {
let result = first & second;
self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.clear_flag(Flags::NSubtract);
self.clear_flag(Flags::Carry);
self.set_flag(Flags::HalfCarry);
result
}
pub(crate) fn xor(&mut self, first: u8, second: u8) -> u8 {
let result = first ^ second;
self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.clear_flag(Flags::NSubtract);
self.clear_flag(Flags::Carry);
self.clear_flag(Flags::HalfCarry);
result
}
pub(crate) fn or(&mut self, first: u8, second: u8) -> u8 {
let result = first | second;
self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.clear_flag(Flags::NSubtract);
self.clear_flag(Flags::Carry);
self.clear_flag(Flags::HalfCarry);
result
}
pub(crate) fn cp(&mut self, first: u8, second: u8) {
self.sub_u8s(first, second, false);
}
pub(crate) fn add(&mut self, first: u8, second: u8) -> u8 {
self.add_u8s(first, second, false)
}
pub(crate) fn adc(&mut self, first: u8, second: u8) -> u8 {
let carry = self.is_flag(Flags::Carry);
self.clear_flag(Flags::Carry);
self.add_u8s(first, second, carry)
}
pub(crate) fn sub(&mut self, first: u8, second: u8) -> u8 {
self.sub_u8s(first, second, false)
}
pub(crate) fn sbc(&mut self, first: u8, second: u8) -> u8 {
self.sub_u8s(first, second, self.is_flag(Flags::Carry))
}
pub(crate) fn inc(&mut self, reg: Reg8) {
let result = self.reg.get_8(reg);
let val = self.inc_raw(result);
self.reg.set_8(reg, val);
}
pub(crate) fn dec(&mut self, reg: Reg8) {
let result = self.reg.get_8(reg);
let val = self.dec_flags(result);
self.reg.set_8(reg, val);
}
pub(crate) fn inc_pair(&mut self, val: u16) -> u16 {
val.wrapping_add(0x1)
}
pub(crate) fn dec_pair(&mut self, val: u16) -> u16 {
val.wrapping_sub(0x1)
}
pub(crate) fn rlc(&mut self, byte: u8) -> u8 {
self.rotate_with_carry(byte, Direction::Left)
}
pub(crate) fn rrc(&mut self, byte: u8) -> u8 {
self.rotate_with_carry(byte, Direction::Right)
}
pub(crate) fn rl(&mut self, byte: u8) -> u8 {
self.rotate(byte, Direction::Left)
}
pub(crate) fn rr(&mut self, byte: u8) -> u8 {
self.rotate(byte, Direction::Right)
}
pub(crate) fn sla(&mut self, byte: u8) -> u8 {
self.shift(byte, Direction::Left)
}
pub(crate) fn sra(&mut self, byte: u8) -> u8 {
let b = get_bit(byte, 7);
let val = self.shift(byte, Direction::Right);
if b {
val + 0b10000000
} else {
val
}
}
pub(crate) fn srl(&mut self, byte: u8) -> u8 {
self.shift(byte, Direction::Right)
}
pub(crate) fn swap(&mut self, byte: u8) -> u8 {
let swapped = (byte & 0x0F) << 4 | (byte & 0xF0) >> 4;
self.set_or_clear_flag(Flags::Zero, swapped == 0x0);
self.clear_flag(Flags::Carry);
self.clear_flag(Flags::HalfCarry);
self.clear_flag(Flags::NSubtract);
swapped
}
pub(crate) fn bit(&mut self, byte: u8, bit: u8) {
self.set_or_clear_flag(Flags::Zero, !get_bit(byte, bit));
self.clear_flag(Flags::NSubtract);
self.set_flag(Flags::HalfCarry);
}
pub(crate) fn rst(&mut self, address: u8) {
self.push(self.reg.pc);
self.reg.pc.set_high(0x0);
self.reg.pc.set_low(address);
}
pub(crate) fn ret(&mut self) {
self.reg.pc = self.pop_word();
}
pub(crate) fn jr(&mut self, jump: i8) {
self.reg.pc = self.reg.pc.wrapping_add_signed(jump.into());
}
}
pub(crate) fn res(byte: u8, bit: u8) -> u8 {
clear_bit(byte, bit)
}
pub(crate) fn set(byte: u8, bit: u8) -> u8 {
set_bit(byte, bit)
}

View file

@ -1,3 +1,154 @@
#[allow(clippy::module_inception)]
pub mod instructions;
pub mod primitives;
use crate::{
connect::{PocketCamera, Renderer},
processor::{memory::mmio::gpu::Colour, Cpu, Direction, Flags, Reg8, SplitRegister},
util::{clear_bit, get_bit, set_bit},
};
impl<ColourFormat, R, C> Cpu<ColourFormat, R, C>
where
ColourFormat: From<Colour> + Copy,
R: Renderer<ColourFormat>,
C: PocketCamera + Send + 'static,
{
pub(crate) fn and(&mut self, first: u8, second: u8) -> u8 {
let result = first & second;
self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.clear_flag(Flags::NSubtract);
self.clear_flag(Flags::Carry);
self.set_flag(Flags::HalfCarry);
result
}
pub(crate) fn xor(&mut self, first: u8, second: u8) -> u8 {
let result = first ^ second;
self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.clear_flag(Flags::NSubtract);
self.clear_flag(Flags::Carry);
self.clear_flag(Flags::HalfCarry);
result
}
pub(crate) fn or(&mut self, first: u8, second: u8) -> u8 {
let result = first | second;
self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.clear_flag(Flags::NSubtract);
self.clear_flag(Flags::Carry);
self.clear_flag(Flags::HalfCarry);
result
}
pub(crate) fn cp(&mut self, first: u8, second: u8) {
self.sub_u8s(first, second, false);
}
pub(crate) fn add(&mut self, first: u8, second: u8) -> u8 {
self.add_u8s(first, second, false)
}
pub(crate) fn adc(&mut self, first: u8, second: u8) -> u8 {
let carry = self.is_flag(Flags::Carry);
self.clear_flag(Flags::Carry);
self.add_u8s(first, second, carry)
}
pub(crate) fn sub(&mut self, first: u8, second: u8) -> u8 {
self.sub_u8s(first, second, false)
}
pub(crate) fn sbc(&mut self, first: u8, second: u8) -> u8 {
self.sub_u8s(first, second, self.is_flag(Flags::Carry))
}
pub(crate) fn inc(&mut self, reg: Reg8) {
let result = self.reg.get_8(reg);
let val = self.inc_raw(result);
self.reg.set_8(reg, val);
}
pub(crate) fn dec(&mut self, reg: Reg8) {
let result = self.reg.get_8(reg);
let val = self.dec_flags(result);
self.reg.set_8(reg, val);
}
pub(crate) fn inc_pair(&mut self, val: u16) -> u16 {
val.wrapping_add(0x1)
}
pub(crate) fn dec_pair(&mut self, val: u16) -> u16 {
val.wrapping_sub(0x1)
}
pub(crate) fn rlc(&mut self, byte: u8) -> u8 {
self.rotate_with_carry(byte, Direction::Left)
}
pub(crate) fn rrc(&mut self, byte: u8) -> u8 {
self.rotate_with_carry(byte, Direction::Right)
}
pub(crate) fn rl(&mut self, byte: u8) -> u8 {
self.rotate(byte, Direction::Left)
}
pub(crate) fn rr(&mut self, byte: u8) -> u8 {
self.rotate(byte, Direction::Right)
}
pub(crate) fn sla(&mut self, byte: u8) -> u8 {
self.shift(byte, Direction::Left)
}
pub(crate) fn sra(&mut self, byte: u8) -> u8 {
let b = get_bit(byte, 7);
let val = self.shift(byte, Direction::Right);
if b {
val + 0b10000000
} else {
val
}
}
pub(crate) fn srl(&mut self, byte: u8) -> u8 {
self.shift(byte, Direction::Right)
}
pub(crate) fn swap(&mut self, byte: u8) -> u8 {
let swapped = (byte & 0x0F) << 4 | (byte & 0xF0) >> 4;
self.set_or_clear_flag(Flags::Zero, swapped == 0x0);
self.clear_flag(Flags::Carry);
self.clear_flag(Flags::HalfCarry);
self.clear_flag(Flags::NSubtract);
swapped
}
pub(crate) fn bit(&mut self, byte: u8, bit: u8) {
self.set_or_clear_flag(Flags::Zero, !get_bit(byte, bit));
self.clear_flag(Flags::NSubtract);
self.set_flag(Flags::HalfCarry);
}
pub(crate) fn rst(&mut self, address: u8) {
self.push(self.reg.pc);
self.reg.pc.set_high(0x0);
self.reg.pc.set_low(address);
}
pub(crate) fn ret(&mut self) {
self.reg.pc = self.pop_word();
}
pub(crate) fn jr(&mut self, jump: i8) {
self.reg.pc = self.reg.pc.wrapping_add_signed(jump.into());
}
}
pub(crate) fn res(byte: u8, bit: u8) -> u8 {
clear_bit(byte, bit)
}
pub(crate) fn set(byte: u8, bit: u8) -> u8 {
set_bit(byte, bit)
}

View file

@ -14,14 +14,12 @@ enum ClockSource {
External,
}
#[allow(dead_code)]
#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
enum ClockSpeed {
Normal,
Fast,
}
#[allow(dead_code)]
#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
struct SerialControl {
transfer_in_progress: bool,

View file

@ -35,9 +35,9 @@ pub(crate) struct UnbufferedSram {
impl UnbufferedSram {
fn new(length: usize) -> Self {
let mut buf = Vec::new();
buf.resize(length, 0);
Self { buf }
Self {
buf: vec![0; length],
}
}
}

View file

@ -1,7 +1,7 @@
use crate::{
connect::{PocketCamera, Renderer},
processor::{
instructions::instructions::{res, set},
instructions::{res, set},
Cpu, Flags, Reg8, SplitRegister,
},
util::as_signed,