its less annoying now lol
This commit is contained in:
parent
1e01308605
commit
30a94868d1
|
@ -88,8 +88,8 @@ fn main() {
|
||||||
.with_no_save(args.no_save)
|
.with_no_save(args.no_save)
|
||||||
.with_verbose(args.verbose);
|
.with_verbose(args.verbose);
|
||||||
|
|
||||||
let tile_window: Option<Box<dyn Renderer<u32>>> = if args.tile_window {
|
let tile_window: Option<WindowRenderer> = if args.tile_window {
|
||||||
Some(Box::new(WindowRenderer::new(factor, None)))
|
Some(WindowRenderer::new(factor, None))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -103,7 +103,7 @@ fn main() {
|
||||||
let mut core = EmulatorCore::init(
|
let mut core = EmulatorCore::init(
|
||||||
receiver,
|
receiver,
|
||||||
options,
|
options,
|
||||||
Box::new(WindowRenderer::new(factor, Some(Gilrs::new().unwrap()))),
|
WindowRenderer::new(factor, Some(Gilrs::new().unwrap())),
|
||||||
output,
|
output,
|
||||||
tile_window,
|
tile_window,
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,7 +12,7 @@ default = []
|
||||||
savestate = []
|
savestate = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gb-emu-lib = { path = "../lib", features = ["async"] }
|
gb-emu-lib = { path = "../lib" }
|
||||||
nih_plug = { path = "../vendored/nih-plug", features = ["standalone"] }
|
nih_plug = { path = "../vendored/nih-plug", features = ["standalone"] }
|
||||||
baseview = { path = "../vendored/baseview" }
|
baseview = { path = "../vendored/baseview" }
|
||||||
pixels = "0.11"
|
pixels = "0.11"
|
||||||
|
|
|
@ -49,7 +49,7 @@ struct EmuParams {
|
||||||
struct EmuVars {
|
struct EmuVars {
|
||||||
rx: AsyncHeapConsumer<[f32; 2]>,
|
rx: AsyncHeapConsumer<[f32; 2]>,
|
||||||
sender: Sender<EmulatorMessage>,
|
sender: Sender<EmulatorMessage>,
|
||||||
emulator_core: EmulatorCore<[u8; 4]>,
|
emulator_core: EmulatorCore<[u8; 4], EmulatorRenderer>,
|
||||||
serial_tx: Sender<u8>,
|
serial_tx: Sender<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,13 +236,11 @@ impl Plugin for GameboyEmu {
|
||||||
DOWNSAMPLE_TYPE,
|
DOWNSAMPLE_TYPE,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (renderer, frame_receiver, key_handler) = EmulatorRenderer::new();
|
let (window, frame_receiver, key_handler) = EmulatorRenderer::new();
|
||||||
|
|
||||||
*self.frame_receiver.lock().unwrap() = Some(frame_receiver);
|
*self.frame_receiver.lock().unwrap() = Some(frame_receiver);
|
||||||
*self.key_handler.lock().unwrap() = Some(key_handler);
|
*self.key_handler.lock().unwrap() = Some(key_handler);
|
||||||
|
|
||||||
let window = Box::new(renderer);
|
|
||||||
|
|
||||||
let (serial_tx, gb_serial_rx) = mpsc::channel::<u8>();
|
let (serial_tx, gb_serial_rx) = mpsc::channel::<u8>();
|
||||||
let serial_target = SerialTarget::Custom {
|
let serial_target = SerialTarget::Custom {
|
||||||
rx: Some(gb_serial_rx),
|
rx: Some(gb_serial_rx),
|
||||||
|
|
|
@ -5,7 +5,6 @@ edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
async = []
|
|
||||||
clocked-serial = []
|
clocked-serial = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
|
@ -20,20 +20,6 @@ pub enum RomFile {
|
||||||
Raw(Vec<u8>),
|
Raw(Vec<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "async")]
|
|
||||||
pub trait Renderer<Format: From<Colour>>: Send {
|
|
||||||
fn prepare(&mut self, width: usize, height: usize);
|
|
||||||
|
|
||||||
fn display(&mut self, buffer: &[Format]);
|
|
||||||
|
|
||||||
fn set_title(&mut self, _title: String) {}
|
|
||||||
|
|
||||||
fn latest_joypad_state(&mut self) -> JoypadState;
|
|
||||||
|
|
||||||
fn set_rumble(&mut self, _rumbling: bool) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "async"))]
|
|
||||||
pub trait Renderer<Format: From<Colour>> {
|
pub trait Renderer<Format: From<Colour>> {
|
||||||
fn prepare(&mut self, width: usize, height: usize);
|
fn prepare(&mut self, width: usize, height: usize);
|
||||||
|
|
||||||
|
|
|
@ -93,18 +93,18 @@ static VERBOSE: OnceCell<bool> = OnceCell::new();
|
||||||
pub const WIDTH: usize = 160;
|
pub const WIDTH: usize = 160;
|
||||||
pub const HEIGHT: usize = 144;
|
pub const HEIGHT: usize = 144;
|
||||||
|
|
||||||
pub struct EmulatorCore<ColourFormat: From<Colour> + Clone> {
|
pub struct EmulatorCore<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>> {
|
||||||
receiver: Receiver<EmulatorMessage>,
|
receiver: Receiver<EmulatorMessage>,
|
||||||
cpu: Cpu<ColourFormat>,
|
cpu: Cpu<ColourFormat, R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ColourFormat: From<Colour> + Clone> EmulatorCore<ColourFormat> {
|
impl<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>> EmulatorCore<ColourFormat, R> {
|
||||||
pub fn init(
|
pub fn init(
|
||||||
receiver: Receiver<EmulatorMessage>,
|
receiver: Receiver<EmulatorMessage>,
|
||||||
options: Options,
|
options: Options,
|
||||||
mut window: Box<dyn Renderer<ColourFormat>>,
|
mut window: R,
|
||||||
output: AudioOutput,
|
output: AudioOutput,
|
||||||
tile_window: Option<Box<dyn Renderer<ColourFormat>>>,
|
tile_window: Option<R>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
if options.verbose {
|
if options.verbose {
|
||||||
VERBOSE.set(true).unwrap();
|
VERBOSE.set(true).unwrap();
|
||||||
|
@ -164,7 +164,7 @@ impl<ColourFormat: From<Colour> + Clone> EmulatorCore<ColourFormat> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(receiver: Receiver<EmulatorMessage>, cpu: Cpu<ColourFormat>) -> Self {
|
fn new(receiver: Receiver<EmulatorMessage>, cpu: Cpu<ColourFormat, R>) -> Self {
|
||||||
Self { receiver, cpu }
|
Self { receiver, cpu }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,15 +217,15 @@ impl<ColourFormat: From<Colour> + Clone> EmulatorCore<ColourFormat> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_save_state(&self) -> CpuSaveState<ColourFormat> {
|
pub fn get_save_state(&self) -> CpuSaveState<ColourFormat, R> {
|
||||||
CpuSaveState::create(&self.cpu)
|
CpuSaveState::create(&self.cpu)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_save_state(
|
pub fn from_save_state(
|
||||||
state: CpuSaveState<ColourFormat>,
|
state: CpuSaveState<ColourFormat, R>,
|
||||||
rom: RomFile,
|
rom: RomFile,
|
||||||
receiver: Receiver<EmulatorMessage>,
|
receiver: Receiver<EmulatorMessage>,
|
||||||
window: Box<dyn Renderer<ColourFormat>>,
|
window: R,
|
||||||
output: AudioOutput,
|
output: AudioOutput,
|
||||||
serial_target: SerialTarget,
|
serial_target: SerialTarget,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
|
connect::Renderer,
|
||||||
processor::{memory::mmio::gpu::Colour, Cpu, Direction, Flags, Reg8, SplitRegister},
|
processor::{memory::mmio::gpu::Colour, Cpu, Direction, Flags, Reg8, SplitRegister},
|
||||||
util::{clear_bit, get_bit, set_bit},
|
util::{clear_bit, get_bit, set_bit},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<ColourFormat: From<Colour> + Clone> Cpu<ColourFormat> {
|
impl<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>> Cpu<ColourFormat, R> {
|
||||||
pub(crate) fn and(&mut self, first: u8, second: u8) -> u8 {
|
pub(crate) fn and(&mut self, first: u8, second: u8) -> u8 {
|
||||||
let result = first & second;
|
let result = first & second;
|
||||||
self.set_or_clear_flag(Flags::Zero, result == 0x0);
|
self.set_or_clear_flag(Flags::Zero, result == 0x0);
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
|
connect::Renderer,
|
||||||
processor::{memory::mmio::gpu::Colour, Cpu, Direction, Flags, SplitRegister},
|
processor::{memory::mmio::gpu::Colour, Cpu, Direction, Flags, SplitRegister},
|
||||||
util::{as_signed, get_bit, get_rotation_carry, rotate, Nibbles},
|
util::{as_signed, get_bit, get_rotation_carry, rotate, Nibbles},
|
||||||
};
|
};
|
||||||
use std::ops::{BitAnd, BitOr};
|
use std::ops::{BitAnd, BitOr};
|
||||||
|
|
||||||
impl<ColourFormat: From<Colour> + Clone> Cpu<ColourFormat> {
|
impl<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>> Cpu<ColourFormat, R> {
|
||||||
pub(crate) fn pop_word(&mut self) -> u16 {
|
pub(crate) fn pop_word(&mut self) -> u16 {
|
||||||
let mut word: u16 = 0x0;
|
let mut word: u16 = 0x0;
|
||||||
word.set_low(self.memory.get(self.reg.sp));
|
word.set_low(self.memory.get(self.reg.sp));
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub(crate) mod rom;
|
||||||
|
|
||||||
pub(crate) type Address = u16;
|
pub(crate) type Address = u16;
|
||||||
|
|
||||||
pub struct Memory<ColourFormat: From<Colour> + Clone> {
|
pub struct Memory<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>> {
|
||||||
bootrom: Option<Vec<u8>>,
|
bootrom: Option<Vec<u8>>,
|
||||||
rom: Rom,
|
rom: Rom,
|
||||||
ram: [u8; 8192],
|
ram: [u8; 8192],
|
||||||
|
@ -32,7 +32,7 @@ pub struct Memory<ColourFormat: From<Colour> + Clone> {
|
||||||
pub(super) ime_scheduled: u8,
|
pub(super) ime_scheduled: u8,
|
||||||
dma_addr: u8,
|
dma_addr: u8,
|
||||||
joypad: Joypad,
|
joypad: Joypad,
|
||||||
gpu: Gpu<ColourFormat>,
|
gpu: Gpu<ColourFormat, R>,
|
||||||
apu: Apu,
|
apu: Apu,
|
||||||
serial: Serial,
|
serial: Serial,
|
||||||
timers: Timer,
|
timers: Timer,
|
||||||
|
@ -40,7 +40,7 @@ pub struct Memory<ColourFormat: From<Colour> + Clone> {
|
||||||
|
|
||||||
#[serde_with::serde_as]
|
#[serde_with::serde_as]
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct MemorySaveState<ColourFormat: From<Colour> + Clone> {
|
pub struct MemorySaveState<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>> {
|
||||||
rom: RomSaveState,
|
rom: RomSaveState,
|
||||||
#[serde_as(as = "[_; 8192]")]
|
#[serde_as(as = "[_; 8192]")]
|
||||||
ram: [u8; 8192],
|
ram: [u8; 8192],
|
||||||
|
@ -51,14 +51,16 @@ pub struct MemorySaveState<ColourFormat: From<Colour> + Clone> {
|
||||||
pub(super) ime_scheduled: u8,
|
pub(super) ime_scheduled: u8,
|
||||||
dma_addr: u8,
|
dma_addr: u8,
|
||||||
joypad: Joypad,
|
joypad: Joypad,
|
||||||
gpu: GpuSaveState<ColourFormat>,
|
gpu: GpuSaveState<ColourFormat, R>,
|
||||||
apu: ApuSaveState,
|
apu: ApuSaveState,
|
||||||
serial: SerialSaveState,
|
serial: SerialSaveState,
|
||||||
timers: Timer,
|
timers: Timer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ColourFormat: From<Colour> + Clone> MemorySaveState<ColourFormat> {
|
impl<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>>
|
||||||
pub fn create(memory: &Memory<ColourFormat>) -> Self {
|
MemorySaveState<ColourFormat, R>
|
||||||
|
{
|
||||||
|
pub fn create(memory: &Memory<ColourFormat, R>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
rom: RomSaveState::create(&memory.rom),
|
rom: RomSaveState::create(&memory.rom),
|
||||||
ram: memory.ram,
|
ram: memory.ram,
|
||||||
|
@ -76,14 +78,14 @@ impl<ColourFormat: From<Colour> + Clone> MemorySaveState<ColourFormat> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ColourFormat: From<Colour> + Clone> Memory<ColourFormat> {
|
impl<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>> Memory<ColourFormat, R> {
|
||||||
pub fn init(
|
pub fn init(
|
||||||
bootrom: Option<Vec<u8>>,
|
bootrom: Option<Vec<u8>>,
|
||||||
rom: Rom,
|
rom: Rom,
|
||||||
window: Box<dyn Renderer<ColourFormat>>,
|
window: R,
|
||||||
output: AudioOutput,
|
output: AudioOutput,
|
||||||
serial_target: SerialTarget,
|
serial_target: SerialTarget,
|
||||||
tile_window: Option<Box<dyn Renderer<ColourFormat>>>,
|
tile_window: Option<R>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
bootrom,
|
bootrom,
|
||||||
|
@ -274,9 +276,9 @@ impl<ColourFormat: From<Colour> + Clone> Memory<ColourFormat> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_save_state(
|
pub fn from_save_state(
|
||||||
state: MemorySaveState<ColourFormat>,
|
state: MemorySaveState<ColourFormat, R>,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
window: Box<dyn Renderer<ColourFormat>>,
|
window: R,
|
||||||
output: AudioOutput,
|
output: AudioOutput,
|
||||||
serial_target: SerialTarget,
|
serial_target: SerialTarget,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -298,7 +300,7 @@ impl<ColourFormat: From<Colour> + Clone> Memory<ColourFormat> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ColourFormat: From<Colour> + Clone> Cpu<ColourFormat> {
|
impl<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>> Cpu<ColourFormat, R> {
|
||||||
pub fn increment_timers(&mut self, machine_cycles: u8) {
|
pub fn increment_timers(&mut self, machine_cycles: u8) {
|
||||||
let steps = (machine_cycles as usize) * 4;
|
let steps = (machine_cycles as usize) * 4;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
tile_window::TileWindow,
|
tile_window::TileWindow,
|
||||||
types::{
|
types::{
|
||||||
|
@ -21,18 +23,18 @@ mod types;
|
||||||
const TILE_WINDOW_WIDTH: usize = 16 * 8;
|
const TILE_WINDOW_WIDTH: usize = 16 * 8;
|
||||||
const TILE_WINDOW_HEIGHT: usize = 24 * 8;
|
const TILE_WINDOW_HEIGHT: usize = 24 * 8;
|
||||||
|
|
||||||
pub struct Gpu<Format: From<Colour>> {
|
pub struct Gpu<Format: From<Colour>, R: Renderer<Format>> {
|
||||||
pub buffer: Vec<Format>,
|
pub buffer: Vec<Format>,
|
||||||
pub vram: Vram,
|
pub vram: Vram,
|
||||||
pub oam: Oam,
|
pub oam: Oam,
|
||||||
pub window: Box<dyn Renderer<Format>>,
|
pub window: R,
|
||||||
is_bg_zero: Vec<bool>,
|
is_bg_zero: Vec<bool>,
|
||||||
lcdc: Lcdc,
|
lcdc: Lcdc,
|
||||||
stat: Stat,
|
stat: Stat,
|
||||||
mode_clock: usize,
|
mode_clock: usize,
|
||||||
scanline: u8,
|
scanline: u8,
|
||||||
lyc: u8,
|
lyc: u8,
|
||||||
tile_window: Option<TileWindow<Format>>,
|
tile_window: Option<TileWindow<Format, R>>,
|
||||||
window_lc: u8,
|
window_lc: u8,
|
||||||
has_window_been_enabled: bool,
|
has_window_been_enabled: bool,
|
||||||
bg_palette: Palette,
|
bg_palette: Palette,
|
||||||
|
@ -46,7 +48,7 @@ pub struct Gpu<Format: From<Colour>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct GpuSaveState<Format: From<Colour>> {
|
pub struct GpuSaveState<Format: From<Colour>, R: Renderer<Format>> {
|
||||||
buffer: Vec<Format>,
|
buffer: Vec<Format>,
|
||||||
vram: Vram,
|
vram: Vram,
|
||||||
oam: Oam,
|
oam: Oam,
|
||||||
|
@ -66,10 +68,12 @@ pub struct GpuSaveState<Format: From<Colour>> {
|
||||||
wx: u8,
|
wx: u8,
|
||||||
wy: u8,
|
wy: u8,
|
||||||
prev_stat: bool,
|
prev_stat: bool,
|
||||||
|
#[serde(skip)]
|
||||||
|
spooky: PhantomData<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Format: From<Colour> + Clone> GpuSaveState<Format> {
|
impl<Format: From<Colour> + Clone, R: Renderer<Format>> GpuSaveState<Format, R> {
|
||||||
pub fn create(gpu: &Gpu<Format>) -> Self {
|
pub fn create(gpu: &Gpu<Format, R>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
buffer: gpu.buffer.clone(),
|
buffer: gpu.buffer.clone(),
|
||||||
vram: gpu.vram,
|
vram: gpu.vram,
|
||||||
|
@ -90,15 +94,13 @@ impl<Format: From<Colour> + Clone> GpuSaveState<Format> {
|
||||||
wx: gpu.wx,
|
wx: gpu.wx,
|
||||||
wy: gpu.wy,
|
wy: gpu.wy,
|
||||||
prev_stat: gpu.prev_stat,
|
prev_stat: gpu.prev_stat,
|
||||||
|
spooky: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Format: From<Colour> + Clone> Gpu<Format> {
|
impl<Format: From<Colour> + Clone, R: Renderer<Format>> Gpu<Format, R> {
|
||||||
pub fn new(
|
pub fn new(window: R, tile_window_renderer: Option<R>) -> Self {
|
||||||
window: Box<dyn Renderer<Format>>,
|
|
||||||
tile_window_renderer: Option<Box<dyn Renderer<Format>>>,
|
|
||||||
) -> Self {
|
|
||||||
let tile_window = if let Some(mut tile_window_renderer) = tile_window_renderer {
|
let tile_window = if let Some(mut tile_window_renderer) = tile_window_renderer {
|
||||||
tile_window_renderer.prepare(TILE_WINDOW_WIDTH, TILE_WINDOW_HEIGHT);
|
tile_window_renderer.prepare(TILE_WINDOW_WIDTH, TILE_WINDOW_HEIGHT);
|
||||||
Some(TileWindow::new(tile_window_renderer))
|
Some(TileWindow::new(tile_window_renderer))
|
||||||
|
@ -133,9 +135,9 @@ impl<Format: From<Colour> + Clone> Gpu<Format> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_save_state(
|
pub fn from_save_state(
|
||||||
state: GpuSaveState<Format>,
|
state: GpuSaveState<Format, R>,
|
||||||
window: Box<dyn Renderer<Format>>,
|
window: R,
|
||||||
tile_window_renderer: Option<Box<dyn Renderer<Format>>>,
|
tile_window_renderer: Option<R>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let tile_window = if let Some(mut tile_window_renderer) = tile_window_renderer {
|
let tile_window = if let Some(mut tile_window_renderer) = tile_window_renderer {
|
||||||
tile_window_renderer.prepare(TILE_WINDOW_WIDTH, TILE_WINDOW_HEIGHT);
|
tile_window_renderer.prepare(TILE_WINDOW_WIDTH, TILE_WINDOW_HEIGHT);
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
use crate::util::{get_bit, set_or_clear_bit};
|
use crate::{
|
||||||
|
connect::Renderer,
|
||||||
|
util::{get_bit, set_or_clear_bit},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
types::{DrawMode, ObjSize, Palette, TiledataArea, TilemapArea},
|
types::{DrawMode, ObjSize, Palette, TiledataArea, TilemapArea},
|
||||||
Colour, Gpu,
|
Colour, Gpu,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<Format: From<Colour>> Gpu<Format> {
|
impl<Format: From<Colour>, R: Renderer<Format>> Gpu<Format, R> {
|
||||||
pub fn update_lcdc(&mut self, data: u8) {
|
pub fn update_lcdc(&mut self, data: u8) {
|
||||||
self.lcdc.enable = get_bit(data, 7);
|
self.lcdc.enable = get_bit(data, 7);
|
||||||
self.lcdc.window_tilemap = if get_bit(data, 6) {
|
self.lcdc.window_tilemap = if get_bit(data, 6) {
|
||||||
|
|
|
@ -6,13 +6,13 @@ use crate::{
|
||||||
|
|
||||||
use super::{types::Vram, Colour};
|
use super::{types::Vram, Colour};
|
||||||
|
|
||||||
pub(super) struct TileWindow<Format: From<Colour>> {
|
pub(super) struct TileWindow<Format: From<Colour>, R: Renderer<Format>> {
|
||||||
sprite_buffer: Vec<Format>,
|
sprite_buffer: Vec<Format>,
|
||||||
sprite_renderer: Box<dyn Renderer<Format>>,
|
sprite_renderer: R,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Format: From<Colour>> TileWindow<Format> {
|
impl<Format: From<Colour>, R: Renderer<Format>> TileWindow<Format, R> {
|
||||||
pub(super) fn new(window: Box<dyn Renderer<Format>>) -> Self {
|
pub(super) fn new(window: R) -> Self {
|
||||||
let mut sprite_buffer = Vec::new();
|
let mut sprite_buffer = Vec::new();
|
||||||
sprite_buffer.reserve_exact(TILE_WINDOW_WIDTH * TILE_WINDOW_HEIGHT);
|
sprite_buffer.reserve_exact(TILE_WINDOW_WIDTH * TILE_WINDOW_HEIGHT);
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@ pub(crate) enum Direction {
|
||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Cpu<ColourFormat: From<Colour> + Clone> {
|
pub struct Cpu<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>> {
|
||||||
pub memory: Memory<ColourFormat>,
|
pub memory: Memory<ColourFormat, R>,
|
||||||
pub reg: Registers,
|
pub reg: Registers,
|
||||||
pub last_instruction: u8,
|
pub last_instruction: u8,
|
||||||
last_instruction_addr: u16,
|
last_instruction_addr: u16,
|
||||||
|
@ -33,8 +33,8 @@ pub struct Cpu<ColourFormat: From<Colour> + Clone> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct CpuSaveState<ColourFormat: From<Colour> + Clone> {
|
pub struct CpuSaveState<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>> {
|
||||||
memory: MemorySaveState<ColourFormat>,
|
memory: MemorySaveState<ColourFormat, R>,
|
||||||
reg: Registers,
|
reg: Registers,
|
||||||
last_instruction: u8,
|
last_instruction: u8,
|
||||||
last_instruction_addr: u16,
|
last_instruction_addr: u16,
|
||||||
|
@ -42,8 +42,8 @@ pub struct CpuSaveState<ColourFormat: From<Colour> + Clone> {
|
||||||
should_halt_bug: bool,
|
should_halt_bug: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ColourFormat: From<Colour> + Clone> CpuSaveState<ColourFormat> {
|
impl<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>> CpuSaveState<ColourFormat, R> {
|
||||||
pub fn create(cpu: &Cpu<ColourFormat>) -> Self {
|
pub fn create(cpu: &Cpu<ColourFormat, R>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
memory: MemorySaveState::create(&cpu.memory),
|
memory: MemorySaveState::create(&cpu.memory),
|
||||||
reg: cpu.reg,
|
reg: cpu.reg,
|
||||||
|
@ -55,8 +55,8 @@ impl<ColourFormat: From<Colour> + Clone> CpuSaveState<ColourFormat> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ColourFormat: From<Colour> + Clone> Cpu<ColourFormat> {
|
impl<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>> Cpu<ColourFormat, R> {
|
||||||
pub fn new(mut memory: Memory<ColourFormat>, run_bootrom: bool) -> Self {
|
pub fn new(mut memory: Memory<ColourFormat, R>, run_bootrom: bool) -> Self {
|
||||||
if !run_bootrom {
|
if !run_bootrom {
|
||||||
memory.cpu_ram_init();
|
memory.cpu_ram_init();
|
||||||
}
|
}
|
||||||
|
@ -155,9 +155,9 @@ impl<ColourFormat: From<Colour> + Clone> Cpu<ColourFormat> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_save_state(
|
pub fn from_save_state(
|
||||||
state: CpuSaveState<ColourFormat>,
|
state: CpuSaveState<ColourFormat, R>,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
window: Box<dyn Renderer<ColourFormat>>,
|
window: R,
|
||||||
output: AudioOutput,
|
output: AudioOutput,
|
||||||
serial_target: SerialTarget,
|
serial_target: SerialTarget,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
|
connect::Renderer,
|
||||||
processor::{
|
processor::{
|
||||||
instructions::instructions::{res, set},
|
instructions::instructions::{res, set},
|
||||||
Cpu, Flags, Reg8, SplitRegister,
|
Cpu, Flags, Reg8, SplitRegister,
|
||||||
|
@ -8,7 +9,7 @@ use crate::{
|
||||||
|
|
||||||
use super::memory::mmio::gpu::Colour;
|
use super::memory::mmio::gpu::Colour;
|
||||||
|
|
||||||
impl<ColourFormat: From<Colour> + Clone> Cpu<ColourFormat> {
|
impl<ColourFormat: From<Colour> + Clone, R: Renderer<ColourFormat>> Cpu<ColourFormat, R> {
|
||||||
pub fn run_opcode(&mut self, opcode: u8) -> u8 {
|
pub fn run_opcode(&mut self, opcode: u8) -> u8 {
|
||||||
match opcode {
|
match opcode {
|
||||||
0x00 => {
|
0x00 => {
|
||||||
|
|
Loading…
Reference in a new issue