aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2017-11-17 15:00:24 -0500
committerDeterminant <ted.sybil@gmail.com>2017-11-17 15:00:24 -0500
commit2f4262c1273108abfcce00e897c520f5a7f4be41 (patch)
tree0915021d63092913de7cc88fe39088f936a4126d
parente2ccf6053d58a2a478814f4a26018989f6fa0f26 (diff)
rearrange the proj
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock119
-rw-r--r--Cargo.toml11
-rw-r--r--README.rst5
-rw-r--r--src/bin.rs (renamed from src/main.rs)97
-rw-r--r--src/cartridge.rs32
-rw-r--r--src/controller.rs34
-rw-r--r--src/disasm.rs97
-rw-r--r--src/lib.rs2
-rw-r--r--src/mapper.rs10
-rw-r--r--src/memory.rs11
-rw-r--r--src/mos6502.rs100
12 files changed, 314 insertions, 205 deletions
diff --git a/.gitignore b/.gitignore
index 143b1ca..0196246 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,3 @@
/target/
**/*.rs.bk
-Cargo.lock
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..30e2288
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,119 @@
+[root]
+name = "runes"
+version = "0.1.0"
+dependencies = [
+ "sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bitflags"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "fuchsia-zircon"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lazy_static"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "num"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-iter"
+version = "0.1.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rand"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "sdl2"
+version = "0.31.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sdl2-sys 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "sdl2-sys"
+version = "0.31.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[metadata]
+"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
+"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
+"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
+"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
+"checksum lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "236eb37a62591d4a41a89b7763d7de3e06ca02d5ab2815446a8bae5d2f8c2d57"
+"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2"
+"checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525"
+"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
+"checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
+"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
+"checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
+"checksum sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a74c2a98a354b20713b90cce70aef9e927e46110d1bc4ef728fd74e0d53eba60"
+"checksum sdl2-sys 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c543ce8a6e33a30cb909612eeeb22e693848211a84558d5a00bb11e791b7ab7"
diff --git a/Cargo.toml b/Cargo.toml
index 8954ae9..566905d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,7 +2,16 @@
name = "runes"
version = "0.1.0"
authors = ["Determinant <tederminant@gmail.com>"]
+description = "A no-std NES emulator library written purely in Rust."
-[dependencies.sdl2]
+[dev-dependencies.sdl2]
version = "0.31"
features = ["unsafe_textures"]
+
+[lib]
+name = "runes"
+path = "src/lib.rs"
+
+[[example]]
+name = "runes"
+path = "src/bin.rs"
diff --git a/README.rst b/README.rst
index 6712025..fc94bbf 100644
--- a/README.rst
+++ b/README.rst
@@ -1,7 +1,7 @@
RuNES
=====
-As we know, there have been a ton of NES emulators implementation in various
+As we know, there have been a ton of NES emulator implementations in various
kinds of languages (mostly C). All of these emulators come with different
accuracy and portability. RuNES is an attempt to build a reasonably
accurate (instruction level accurate), light-weight and efficient emulation
@@ -38,4 +38,5 @@ Build
::
- cargo build --release
+ cargo build --release # build the library only (no std dep)
+ cargo build --examples --release # or build the example emulator (requires std)
diff --git a/src/main.rs b/src/bin.rs
index 6a350ff..a66b430 100644
--- a/src/main.rs
+++ b/src/bin.rs
@@ -11,7 +11,7 @@ use std::io::Read;
use core::cell::RefCell;
use core::intrinsics::transmute;
use cartridge::*;
-use controller::stdctl::{Joystick, Button};
+use controller::stdctl;
use std::time::{Instant, Duration};
use std::thread::sleep;
@@ -42,6 +42,40 @@ const FB_SIZE: usize = PIX_HEIGHT * FB_PITCH * (PIXEL_SIZE as usize);
const WIN_WIDTH: u32 = PIX_WIDTH as u32 * PIXEL_SIZE;
const WIN_HEIGHT: u32 = PIX_HEIGHT as u32 * PIXEL_SIZE;
+pub struct SimpleCart {
+ chr_rom: Vec<u8>,
+ prg_rom: Vec<u8>,
+ sram: Vec<u8>,
+ pub mirror_type: MirrorType
+}
+
+impl SimpleCart {
+ pub fn new(chr_rom: Vec<u8>,
+ prg_rom: Vec<u8>,
+ sram: Vec<u8>,
+ mirror_type: MirrorType) -> Self {
+ SimpleCart{chr_rom, prg_rom, sram, mirror_type}
+ }
+}
+
+impl Cartridge for SimpleCart {
+ fn get_size(&self, kind: BankType) -> usize {
+ match kind {
+ BankType::PrgRom => self.prg_rom.len(),
+ BankType::ChrRom => self.chr_rom.len(),
+ BankType::Sram => self.sram.len()
+ }
+ }
+ fn get_bank(&mut self, base: usize, size: usize, kind: BankType) -> *mut [u8] {
+ &mut (match kind {
+ BankType::PrgRom => &mut self.prg_rom,
+ BankType::ChrRom => &mut self.chr_rom,
+ BankType::Sram => &mut self.sram,
+ })[base..base + size]
+ }
+ fn get_mirror_type(&self) -> MirrorType {self.mirror_type}
+}
+
struct SDLWindow<'a> {
canvas: sdl2::render::WindowCanvas,
events: sdl2::EventPump,
@@ -49,9 +83,9 @@ struct SDLWindow<'a> {
texture: sdl2::render::Texture,
timer: Instant,
duration_per_frame: Duration,
- p1_button_states: [bool; 8],
- p1_ctl: &'a Joystick,
- p1_keymap: [Button; 256],
+ p1_button_state: u8,
+ p1_ctl: &'a stdctl::Joystick,
+ p1_keymap: [u8; 256],
}
macro_rules! gen_keymap {
@@ -65,7 +99,7 @@ macro_rules! gen_keymap {
}
impl<'a> SDLWindow<'a> {
- fn new(p1_ctl: &'a Joystick) -> Self {
+ fn new(p1_ctl: &'a stdctl::Joystick) -> Self {
use Keycode::*;
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
@@ -89,23 +123,23 @@ impl<'a> SDLWindow<'a> {
PixelFormatEnum::RGB24, WIN_WIDTH, WIN_HEIGHT).unwrap(),
timer: Instant::now(),
duration_per_frame: Duration::from_millis(1000 / 60),
- p1_button_states: [false; 8],
- p1_ctl, p1_keymap: [Button::Null; 256]
+ p1_button_state: 0,
+ p1_ctl, p1_keymap: [stdctl::NULL; 256]
};
{
let keymap = &mut res.p1_keymap;
- gen_keymap!(keymap, [I, Button::Up,
- K, Button::Down,
- J, Button::Left,
- L, Button::Right,
- Z, Button::A,
- X, Button::B,
- Return, Button::Start,
- S, Button::Select,
- Up, Button::Up,
- Down, Button::Down,
- Left, Button::Left,
- Right, Button::Right
+ gen_keymap!(keymap, [I, stdctl::UP,
+ K, stdctl::DOWN,
+ J, stdctl::LEFT,
+ L, stdctl::RIGHT,
+ Z, stdctl::A,
+ X, stdctl::B,
+ Return, stdctl::START,
+ S, stdctl::SELECT,
+ Up, stdctl::UP,
+ Down, stdctl::DOWN,
+ Left, stdctl::LEFT,
+ Right, stdctl::RIGHT
]);
}
res
@@ -114,7 +148,6 @@ impl<'a> SDLWindow<'a> {
#[inline]
fn poll(&mut self) -> bool {
use Keycode::*;
- let p1_button_states = &mut self.p1_button_states;
let p1_keymap = &self.p1_keymap;
for event in self.events.poll_iter() {
match event {
@@ -122,22 +155,12 @@ impl<'a> SDLWindow<'a> {
return true;
},
Event::KeyDown { keycode: Some(c), .. } => {
- match p1_keymap[(c as usize) & 0xff] {
- Button::Null => (),
- i => {
- p1_button_states[i as usize] = true;
- self.p1_ctl.set(p1_button_states);
- }
- }
+ self.p1_button_state |= p1_keymap[(c as usize) & 0xff];
+ self.p1_ctl.set(self.p1_button_state)
},
Event::KeyUp { keycode: Some(c), .. } => {
- match p1_keymap[(c as usize) & 0xff] {
- Button::Null => (),
- i => {
- p1_button_states[i as usize] = false;
- self.p1_ctl.set(p1_button_states);
- }
- }
+ self.p1_button_state &= !p1_keymap[(c as usize) & 0xff];
+ self.p1_ctl.set(self.p1_button_state)
},
_ => ()
}
@@ -258,13 +281,13 @@ fn main() {
}
}
*/
- let p1ctl = Joystick::new();
+ let p1ctl = stdctl::Joystick::new();
let mut win = SDLWindow::new(&p1ctl);
let mut m = match mapper_id {
- 0 | 2 => mapper::Mapper2::new(cartridge::Cartridge::new(chr_rom, prg_rom, sram, mirror)),
+ 0 | 2 => mapper::Mapper2::new(SimpleCart::new(chr_rom, prg_rom, sram, mirror)),
_ => panic!("unsupported mapper {}", mapper_id)
};
- let mt = m.get_cart().mirror_type;
+ let mt = m.get_cart().get_mirror_type();
let mapper = RefCell::new(&mut m as &mut memory::VMem);
let mut ppu = ppu::PPU::new(memory::PPUMemory::new(&mapper, mt), &mut win);
let mut cpu = mos6502::CPU::new(memory::CPUMemory::new(&mut ppu, &mapper, Some(&p1ctl), None));
diff --git a/src/cartridge.rs b/src/cartridge.rs
index 0d21a42..524ef12 100644
--- a/src/cartridge.rs
+++ b/src/cartridge.rs
@@ -15,32 +15,8 @@ pub enum BankType {
Sram, /* save ram */
}
-pub struct Cartridge {
- chr_rom: Vec<u8>,
- prg_rom: Vec<u8>,
- sram: Vec<u8>,
- pub mirror_type: MirrorType
-}
-
-impl Cartridge {
- pub fn get_size(&self, kind: BankType) -> usize {
- match kind {
- BankType::PrgRom => self.prg_rom.len(),
- BankType::ChrRom => self.chr_rom.len(),
- BankType::Sram => self.sram.len()
- }
- }
- pub fn get_bank(&mut self, base: usize, size: usize, kind: BankType) -> *mut [u8] {
- &mut (match kind {
- BankType::PrgRom => &mut self.prg_rom,
- BankType::ChrRom => &mut self.chr_rom,
- BankType::Sram => &mut self.sram,
- })[base..base + size]
- }
- pub fn new(chr_rom: Vec<u8>,
- prg_rom: Vec<u8>,
- sram: Vec<u8>,
- mirror_type: MirrorType) -> Self {
- Cartridge{chr_rom, prg_rom, sram, mirror_type}
- }
+pub trait Cartridge {
+ fn get_size(&self, kind: BankType) -> usize;
+ fn get_bank(&mut self, base: usize, size: usize, kind: BankType) -> *mut [u8];
+ fn get_mirror_type(&self) -> MirrorType;
}
diff --git a/src/controller.rs b/src/controller.rs
index 2685cd1..f2ed4f7 100644
--- a/src/controller.rs
+++ b/src/controller.rs
@@ -8,18 +8,16 @@ pub trait Controller {
pub mod stdctl {
use core::cell::Cell;
use controller::Controller;
- #[derive(Copy, Clone)]
- pub enum Button {
- A = 0,
- B = 1,
- Select = 2,
- Start = 3,
- Up = 4,
- Down = 5,
- Left = 6,
- Right = 7,
- Null = 8,
- }
+ pub const A: u8 = 1 << 0;
+ pub const B: u8 = 1 << 1;
+ pub const SELECT: u8 = 1 << 2;
+ pub const START: u8 = 1 << 3;
+ pub const UP: u8 = 1 << 4;
+ pub const DOWN: u8 = 1 << 5;
+ pub const LEFT: u8 = 1 << 6;
+ pub const RIGHT: u8 = 1 << 7;
+ pub const NULL: u8 = 0;
+
pub struct Joystick {
strobe: Cell<bool>,
reg: Cell<u8>,
@@ -31,15 +29,9 @@ pub mod stdctl {
Joystick{reg: Cell::new(0), strobe: Cell::new(false), back_reg: Cell::new(0)}
}
- pub fn set(&self, buttons: &[bool]) {
- let mut reg = 0;
- for (i, v) in buttons.iter().enumerate() {
- if *v {
- reg |= 1 << i;
- }
- }
- self.reg.set(reg);
- self.back_reg.set(reg);
+ pub fn set(&self, buttons: u8) {
+ self.reg.set(buttons);
+ self.back_reg.set(buttons);
}
}
diff --git a/src/disasm.rs b/src/disasm.rs
new file mode 100644
index 0000000..c9b3696
--- /dev/null
+++ b/src/disasm.rs
@@ -0,0 +1,97 @@
+use mos6502::{make_optable, make_addrtable};
+
+mod disops {
+ make_optable!(OPS, &str);
+ ids2strs!(adc, and, asl, bcc, bcs, beq, bit, bmi,
+ bne, bpl, brk, bvc, bvs, clc, cld, cli,
+ clv, cmp, cpx, cpy, dec, dex, dey, eor,
+ inc, inx, iny, jmp, jsr, lda, ldx, ldy,
+ lsr, nop, ora, pha, php, pla, plp, rol,
+ ror, rti, rts, sbc, sec, sed, sei, sta,
+ stx, sty, tax, tay, tsx, txa, txs, tya, nil);
+}
+
+mod disaddr {
+ pub type T<'a, 'b> = &'a mut Iterator<Item=&'b u8>;
+ make_addrtable!(ADDR_MODES, fn (T) -> String);
+ fn acc(_code: T) -> String {
+ "a".to_string()
+ }
+ fn imm(code: T) -> String {
+ format!("#${:02x}", code.next().unwrap())
+ }
+ fn zpg(code: T) -> String {
+ format!("${:02x}", code.next().unwrap())
+ }
+ fn zpx(code: T) -> String {
+ format!("${:02x}, x", code.next().unwrap())
+ }
+ fn zpy(code: T) -> String {
+ format!("${:02x}, y", code.next().unwrap())
+ }
+ fn rel(code: T) -> String {
+ let b = *code.next().unwrap() as i8 as i16;
+ if b >= 0 {
+ format!("+${:02x}, x", b)
+ } else {
+ format!("-${:02x}, x", -b)
+ }
+ }
+ fn abs(code: T) -> String {
+ let low = *code.next().unwrap() as u16;
+ let high = *code.next().unwrap() as u16;
+ format!("${:04x}", (high << 8) | low)
+ }
+ fn abx(code: T) -> String {
+ let low = *code.next().unwrap() as u16;
+ let high = *code.next().unwrap() as u16;
+ format!("${:04x}, x", (high << 8) | low)
+ }
+ fn aby(code: T) -> String {
+ let low = *code.next().unwrap() as u16;
+ let high = *code.next().unwrap() as u16;
+ format!("${:04x}, y", (high << 8) | low)
+ }
+ fn ind(code: T) -> String {
+ let low = *code.next().unwrap() as u16;
+ let high = *code.next().unwrap() as u16;
+ format!("(${:04x})", (high << 8) | low)
+ }
+ fn xin(code: T) -> String {
+ format!("(${:02x}, x)", code.next().unwrap())
+ }
+ fn iny(code: T) -> String {
+ format!("(${:02x}), y", code.next().unwrap())
+ }
+ fn nil(_code: T) -> String {
+ "".to_string()
+ }
+}
+
+pub struct Disassembler<'a, T> where T: Iterator<Item=&'a u8> {
+ raw_code: T
+}
+
+impl<'a, T> Disassembler<'a, T> where T: Iterator<Item=&'a u8> {
+ pub fn new(raw_code: T) -> Self {
+ Disassembler{raw_code}
+ }
+ fn parse(opcode: u8, code: &mut T) -> String {
+ format!("{} {}", disops::OPS[opcode as usize],
+ disaddr::ADDR_MODES[opcode as usize](code))
+ }
+}
+
+impl<'a, T> Iterator for Disassembler<'a, T> where T: Iterator<Item=&'a u8> {
+ type Item = String;
+ fn next(&mut self) -> Option<Self::Item> {
+ match self.raw_code.next() {
+ Some(opcode) => Some(Disassembler::parse(*opcode, &mut self.raw_code)),
+ None => None
+ }
+ }
+}
+
+pub fn parse(opcode: u8, code: &[u8]) -> String {
+ Disassembler::parse(opcode, &mut code.iter())
+}
diff --git a/src/lib.rs b/src/lib.rs
index 0c35e3d..18ec0a0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,4 @@
-extern crate core;
+#![no_std]
mod memory;
mod mos6502;
mod ppu;
diff --git a/src/mapper.rs b/src/mapper.rs
index fc02ed2..583c452 100644
--- a/src/mapper.rs
+++ b/src/mapper.rs
@@ -3,8 +3,8 @@ extern crate core;
use memory::VMem;
use cartridge::{Cartridge, BankType};
-pub struct Mapper2<'a> {
- cart: Cartridge,
+pub struct Mapper2<'a, C> where C: Cartridge {
+ cart: C,
prg_bank1: &'a [u8],
prg_bank2: &'a [u8],
chr_bank: &'a mut [u8],
@@ -12,7 +12,7 @@ pub struct Mapper2<'a> {
prg_nbank: usize
}
-impl<'a> VMem for Mapper2<'a> {
+impl<'a, C> VMem for Mapper2<'a, C> where C: Cartridge {
fn read(&self, addr: u16) -> u8 {
let addr = addr as usize;
if addr < 0x2000 { /* 0x2000 size bank */
@@ -46,8 +46,8 @@ impl<'a> VMem for Mapper2<'a> {
}
}
-impl<'a> Mapper2<'a> {
- pub fn new(cart: Cartridge) -> Self {
+impl<'a, C> Mapper2<'a, C> where C: Cartridge {
+ pub fn new(cart: C) -> Self {
unsafe {
let nbank = cart.get_size(BankType::PrgRom) >> 14;
let null = core::mem::uninitialized();
diff --git a/src/memory.rs b/src/memory.rs
index 6a62678..fb07ad5 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -115,17 +115,6 @@ impl<'a> PPUMemory<'a> {
mirror_type,
mapper}
}
-
- pub fn dump(&self) {
- for (i, v) in self.palette.iter().enumerate() {
- print!("{:02x} ", *v);
- if (i & 0x7) == 0x7 {println!("@{:02x}", i)}
- }
- for (i, v) in self.nametable.iter().enumerate() {
- print!("{:02x} ", *v);
- if (i & 0x1f) == 0x1f {println!("@{:02x}", i)}
- }
- }
}
const MIRROR_IDX: [[u8; 4]; 5] = [
diff --git a/src/mos6502.rs b/src/mos6502.rs
index 9dd3d85..f279a2a 100644
--- a/src/mos6502.rs
+++ b/src/mos6502.rs
@@ -1,4 +1,6 @@
#![allow(dead_code)]
+#![allow(unused_macros)]
+
use memory::{CPUMemory, VMem};
pub const CPU_FREQ: u32 = 1789773;
macro_rules! make_optable {
@@ -121,104 +123,6 @@ macro_rules! ids2strs {
};
}
-pub mod disasm {
- mod disops {
- make_optable!(OPS, &str);
- ids2strs!(adc, and, asl, bcc, bcs, beq, bit, bmi,
- bne, bpl, brk, bvc, bvs, clc, cld, cli,
- clv, cmp, cpx, cpy, dec, dex, dey, eor,
- inc, inx, iny, jmp, jsr, lda, ldx, ldy,
- lsr, nop, ora, pha, php, pla, plp, rol,
- ror, rti, rts, sbc, sec, sed, sei, sta,
- stx, sty, tax, tay, tsx, txa, txs, tya, nil);
- }
-
- mod disaddr {
- pub type T<'a, 'b> = &'a mut Iterator<Item=&'b u8>;
- make_addrtable!(ADDR_MODES, fn (T) -> String);
- fn acc(_code: T) -> String {
- "a".to_string()
- }
- fn imm(code: T) -> String {
- format!("#${:02x}", code.next().unwrap())
- }
- fn zpg(code: T) -> String {
- format!("${:02x}", code.next().unwrap())
- }
- fn zpx(code: T) -> String {
- format!("${:02x}, x", code.next().unwrap())
- }
- fn zpy(code: T) -> String {
- format!("${:02x}, y", code.next().unwrap())
- }
- fn rel(code: T) -> String {
- let b = *code.next().unwrap() as i8 as i16;
- if b >= 0 {
- format!("+${:02x}, x", b)
- } else {
- format!("-${:02x}, x", -b)
- }
- }
- fn abs(code: T) -> String {
- let low = *code.next().unwrap() as u16;
- let high = *code.next().unwrap() as u16;
- format!("${:04x}", (high << 8) | low)
- }
- fn abx(code: T) -> String {
- let low = *code.next().unwrap() as u16;
- let high = *code.next().unwrap() as u16;
- format!("${:04x}, x", (high << 8) | low)
- }
- fn aby(code: T) -> String {
- let low = *code.next().unwrap() as u16;
- let high = *code.next().unwrap() as u16;
- format!("${:04x}, y", (high << 8) | low)
- }
- fn ind(code: T) -> String {
- let low = *code.next().unwrap() as u16;
- let high = *code.next().unwrap() as u16;
- format!("(${:04x})", (high << 8) | low)
- }
- fn xin(code: T) -> String {
- format!("(${:02x}, x)", code.next().unwrap())
- }
- fn iny(code: T) -> String {
- format!("(${:02x}), y", code.next().unwrap())
- }
- fn nil(_code: T) -> String {
- "".to_string()
- }
- }
-
- pub struct Disassembler<'a, T> where T: Iterator<Item=&'a u8> {
- raw_code: T
- }
-
- impl<'a, T> Disassembler<'a, T> where T: Iterator<Item=&'a u8> {
- pub fn new(raw_code: T) -> Self {
- Disassembler{raw_code}
- }
- fn parse(opcode: u8, code: &mut T) -> String {
- format!("{} {}", disops::OPS[opcode as usize],
- disaddr::ADDR_MODES[opcode as usize](code))
- }
- }
-
- impl<'a, T> Iterator for Disassembler<'a, T> where T: Iterator<Item=&'a u8> {
- type Item = String;
- fn next(&mut self) -> Option<Self::Item> {
- match self.raw_code.next() {
- Some(opcode) => Some(Disassembler::parse(*opcode, &mut self.raw_code)),
- None => None
- }
- }
- }
-
- pub fn parse(opcode: u8, code: &[u8]) -> String {
- Disassembler::parse(opcode, &mut code.iter())
- }
-}
-
macro_rules! stack_addr {
($sp: ident, $disp: expr) => (($sp.wrapping_sub($disp) as u16) | 0x0100);
}