aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2017-11-26 12:46:37 -0500
committerDeterminant <ted.sybil@gmail.com>2017-11-26 12:46:37 -0500
commit3fac7315288e066b9c31b85d55ec7751159b958e (patch)
treed8f506375083370a7e08f6af3b19316f1952034a
parent6aa7a3da39bef2692a70f487d2997061c336616e (diff)
...
-rw-r--r--src/bin.rs81
-rw-r--r--src/lib.rs4
-rw-r--r--src/memory.rs28
3 files changed, 103 insertions, 10 deletions
diff --git a/src/bin.rs b/src/bin.rs
index beb41d9..852c88b 100644
--- a/src/bin.rs
+++ b/src/bin.rs
@@ -14,6 +14,7 @@ use sdl2::rect::Rect;
use sdl2::pixels::PixelFormatEnum;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
+use sdl2::audio::{AudioSpecDesired};
mod memory;
#[macro_use] mod mos6502;
@@ -26,7 +27,8 @@ mod disasm;
use mos6502::CPU;
use ppu::PPU;
-use memory::{CPUMemory, PPUMemory};
+use apu::APU;
+use memory::{CPUMemory, PPUMemory, VMem};
use cartridge::{BankType, MirrorType, Cartridge};
use controller::stdctl;
@@ -107,9 +109,8 @@ macro_rules! gen_keymap {
}
impl<'a> SDLWindow<'a> {
- fn new(p1_ctl: &'a stdctl::Joystick) -> Self {
+ fn new(sdl_context: &'a sdl2::Sdl, p1_ctl: &'a stdctl::Joystick) -> Self {
use Keycode::*;
- let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem.window("RuNES", WIN_WIDTH, WIN_HEIGHT)
.position_centered()
@@ -183,6 +184,7 @@ fn get_rgb(color: u8) -> (u8, u8, u8) {
((c >> 16) as u8, ((c >> 8) & 0xff) as u8, (c & 0xff) as u8)
}
+
impl<'a> ppu::Screen for SDLWindow<'a> {
fn put(&mut self, x: u8, y: u8, color: u8) {
let (r, g, b) = get_rgb(color);
@@ -218,13 +220,77 @@ impl<'a> ppu::Screen for SDLWindow<'a> {
sleep(diff);
//println!("{} faster", diff.subsec_nanos() as f64 / 1e6);
} else {
- //println!("{} slower", (e - duration_per_frame).subsec_nanos() as f64 / 1e6);
+ //println!("{} slower", (e - self.duration_per_frame).subsec_nanos() as f64 / 1e6);
}
self.timer = Instant::now();
//canvas.set_draw_color(Color::RGB(128, 128, 128));
}
}
+struct SDLAudio {
+ device: sdl2::audio::AudioQueue<i16>,
+ buffer: [i16; 1],
+ buffer_cnt: usize
+}
+
+/*
+fn gen_wave(bytes_to_write: i32) -> Vec<i16> {
+ // Generate a square wave
+ let tone_volume = 1_000i16;
+ let period = 48_000 / 256;
+ let sample_count = bytes_to_write;
+ let mut result = Vec::new();
+
+ for x in 0..sample_count {
+ result.push(
+ if (x / period) % 2 == 0 {
+ tone_volume
+ }
+ else {
+ -tone_volume
+ }
+ );
+ }
+ result
+}
+*/
+
+impl SDLAudio {
+ fn new(sdl_context: &sdl2::Sdl) -> Self {
+ let audio_subsystem = sdl_context.audio().unwrap();
+ let desired_spec = AudioSpecDesired {
+ freq: Some(apu::AUDIO_SAMPLE_FREQ as i32),
+ channels: Some(1),
+ samples: Some(4096)
+ };
+ let device = audio_subsystem.open_queue::<i16, _>(None, &desired_spec).unwrap();
+ let t = SDLAudio {
+ device, buffer: [0; 1], buffer_cnt: 0
+ };
+ t.device.resume();
+ t
+ }
+
+ fn flush(&mut self) {
+ self.device.queue(&self.buffer[..self.buffer_cnt]);
+ self.buffer_cnt = 0;
+ }
+}
+
+impl apu::Speaker for SDLAudio {
+ fn queue(&mut self, sample: u16) {
+ self.buffer[self.buffer_cnt] = sample.wrapping_sub(32768) as i16;
+ self.buffer_cnt += 1;
+ if self.buffer_cnt == self.buffer.len() {
+ self.flush()
+ }
+ }
+
+ fn push(&mut self) {
+ self.flush();
+ }
+}
+
#[repr(C, packed)]
struct INesHeader {
magic: [u8; 4],
@@ -294,9 +360,11 @@ fn main() {
}
}
*/
+ let sdl_context = sdl2::init().unwrap();
let p1ctl = stdctl::Joystick::new();
let cart = SimpleCart::new(chr_rom, prg_rom, sram, mirror);
- let mut win = SDLWindow::new(&p1ctl);
+ let mut win = SDLWindow::new(&sdl_context, &p1ctl);
+ let mut spkr = SDLAudio::new(&sdl_context);
let mut m: Box<mapper::Mapper> = match mapper_id {
0 | 2 => Box::new(mapper::Mapper2::new(cart)),
1 => Box::new(mapper::Mapper1::new(cart)),
@@ -305,8 +373,9 @@ fn main() {
let mapper = RefCell::new(&mut (*m) as &mut mapper::Mapper);
let mut cpu = CPU::new(CPUMemory::new(&mapper, Some(&p1ctl), None));
let mut ppu = PPU::new(PPUMemory::new(&mapper), &mut win);
+ let mut apu = APU::new(&mut spkr);
let cpu_ptr = &mut cpu as *mut CPU;
- cpu.mem.bus.attach(cpu_ptr, &mut ppu);
+ cpu.mem.bus.attach(cpu_ptr, &mut ppu, &mut apu);
cpu.start();
loop {
while cpu.cycle > 0 {
diff --git a/src/lib.rs b/src/lib.rs
index 266f8a6..6439124 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,9 @@
-#![no_std]
+//#![no_std]
+extern crate core;
mod memory;
#[macro_use] mod mos6502;
mod ppu;
+mod apu;
mod cartridge;
mod mapper;
mod controller;
diff --git a/src/memory.rs b/src/memory.rs
index cfdf422..bea84fc 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -1,5 +1,6 @@
#![allow(dead_code)]
use ppu::PPU;
+use apu::APU;
use mos6502::CPU;
use cartridge::MirrorType;
use mapper::Mapper;
@@ -15,21 +16,27 @@ pub trait VMem {
pub struct Bus<'a> {
cpu: *mut CPU<'a>,
ppu: *mut PPU<'a>,
+ apu: *mut APU<'a>
}
impl<'a> Bus<'a> {
pub fn new() -> Self {
Bus {ppu: null_mut(),
- cpu: null_mut()}
+ cpu: null_mut(),
+ apu: null_mut()}
}
- pub fn attach(&mut self, cpu: *mut CPU<'a>, ppu: *mut PPU<'a>) {
+ pub fn attach(&mut self, cpu: *mut CPU<'a>,
+ ppu: *mut PPU<'a>,
+ apu: *mut APU<'a>) {
self.ppu = ppu;
self.cpu = cpu;
+ self.apu = apu;
}
#[inline(always)] fn get_cpu(&self) -> &'a mut CPU<'a> {unsafe{&mut *self.cpu}}
#[inline(always)] fn get_ppu(&self) -> &'a mut PPU<'a> {unsafe{&mut *self.ppu}}
+ #[inline(always)] fn get_apu(&self) -> &'a mut APU<'a> {unsafe{&mut *self.apu}}
}
pub struct CPUMemory<'a> {
@@ -53,8 +60,12 @@ impl<'a> CPUMemory<'a> {
pub fn ppu_tick(&self) {
let cpu = self.bus.get_cpu();
let ppu = self.bus.get_ppu();
+ let apu = self.bus.get_apu();
if ppu.tick() || ppu.tick() || ppu.tick() {
- cpu.trigger_nmi();
+ cpu.trigger_nmi()
+ }
+ if apu.tick() {
+ cpu.trigger_irq()
}
cpu.cycle -= 1;
}
@@ -112,7 +123,18 @@ impl<'a> VMem for CPUMemory<'a> {
_ => panic!("invalid ppu reg write access at 0x{:04x}", addr)
}
} else if addr < 0x4020 {
+ let apu = self.bus.get_apu();
match addr {
+ 0x4000 => apu.pulse1.write_reg1(data),
+ 0x4001 => apu.pulse1.write_reg2(data),
+ 0x4002 => apu.pulse1.write_reg3(data),
+ 0x4003 => apu.pulse1.write_reg4(data),
+ 0x4004 => apu.pulse2.write_reg1(data),
+ 0x4005 => apu.pulse2.write_reg2(data),
+ 0x4006 => apu.pulse2.write_reg3(data),
+ 0x4007 => apu.pulse2.write_reg4(data),
+ 0x4015 => apu.write_status(data),
+ 0x4017 => apu.write_frame_counter(data),
0x4014 => ppu.write_oamdma(data, cpu),
0x4016 => {
if let Some(c) = self.ctl1 { c.write(data) }