some bug fixes
This commit is contained in:
27
src/main.rs
27
src/main.rs
@@ -16,6 +16,7 @@ use nes::cartridge::*;
|
|||||||
use nes::disasm::*;
|
use nes::disasm::*;
|
||||||
use opengl_graphics::OpenGL;
|
use opengl_graphics::OpenGL;
|
||||||
use log::Level;
|
use log::Level;
|
||||||
|
use failure::Error;
|
||||||
|
|
||||||
use gfx_glyph::{Section, GlyphBrushBuilder,GlyphBrush, Scale};
|
use gfx_glyph::{Section, GlyphBrushBuilder,GlyphBrush, Scale};
|
||||||
use gfx_device_gl::{Resources,Factory};
|
use gfx_device_gl::{Resources,Factory};
|
||||||
@@ -25,19 +26,19 @@ const BG_COLOR: [f32; 4] = [0.0, 0.0, 252.0/256.0, 1.0];
|
|||||||
// font options
|
// font options
|
||||||
const FT_SIZE_PX: f32 = 11.0;
|
const FT_SIZE_PX: f32 = 11.0;
|
||||||
const FT_COLOR_WHITE: [f32; 4] = [1.0; 4];
|
const FT_COLOR_WHITE: [f32; 4] = [1.0; 4];
|
||||||
const FT_COLOR_RED: [f32; 4] = [168.0/256.0, 0.0, 32.0/256.0, 1.0];
|
const FT_COLOR_RED: [f32; 4] = [168.0/256.0, 32.0/256.0, 0.0, 1.0];
|
||||||
const FT_COLOR_GREEN: [f32; 4] = [0.0, 168.0/256.0, 0.0, 1.0];
|
const FT_COLOR_GREEN: [f32; 4] = [0.0, 168.0/256.0, 0.0, 1.0];
|
||||||
const FT_LINE_DISTANCE: f32 = FT_SIZE_PX * 0.5;
|
const FT_LINE_DISTANCE: f32 = FT_SIZE_PX * 0.5;
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref FT_SCALE: Scale = Scale::uniform(FT_SIZE_PX);
|
static ref FT_SCALE: Scale = Scale::uniform(FT_SIZE_PX);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() -> Result<(), Error> {
|
||||||
simple_logger::init_with_level(Level::Error).unwrap();
|
simple_logger::init_with_level(Level::Debug).unwrap();
|
||||||
|
|
||||||
let mut bus = MemoryBus::new();
|
let mut bus = MemoryBus::new();
|
||||||
let cartridge = Path::new("test_roms/registers.nes");
|
let cartridge = Path::new("test_roms/nestest.nes");
|
||||||
let cartridge = Cartridge::new(cartridge).unwrap();
|
let cartridge = Cartridge::new(cartridge)?;
|
||||||
bus.insert_cartrige(cartridge);
|
bus.insert_cartrige(cartridge);
|
||||||
|
|
||||||
// Load little test program into ram
|
// Load little test program into ram
|
||||||
@@ -55,7 +56,7 @@ fn main() {
|
|||||||
// bus.writew(0xfffc, offset);
|
// bus.writew(0xfffc, offset);
|
||||||
|
|
||||||
// disassemble instructions
|
// disassemble instructions
|
||||||
let disasm = Disasm::disassemble(&bus, 0xe1ff, 0xffff-2).unwrap();
|
let disasm = Disasm::disassemble(&bus, 0xC000, 0xFFFF).unwrap();
|
||||||
// println!("{:?}", disasm.instructions);
|
// println!("{:?}", disasm.instructions);
|
||||||
// return;
|
// return;
|
||||||
// let disasm = Disasm::disassemble(&[], 0x000).unwrap();
|
// let disasm = Disasm::disassemble(&[], 0x000).unwrap();
|
||||||
@@ -63,6 +64,8 @@ fn main() {
|
|||||||
// Create and reset CPU
|
// Create and reset CPU
|
||||||
let mut cpu: CPU = CPU::new();
|
let mut cpu: CPU = CPU::new();
|
||||||
cpu.find_pc_addr(&bus);
|
cpu.find_pc_addr(&bus);
|
||||||
|
cpu.regs.pc = 0xC000;
|
||||||
|
// return Ok(());
|
||||||
// cpu.reset(&bus);
|
// cpu.reset(&bus);
|
||||||
|
|
||||||
// Prepare window and drawing resources
|
// Prepare window and drawing resources
|
||||||
@@ -115,6 +118,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(window: &mut PistonWindow, event: &Event,
|
fn render(window: &mut PistonWindow, event: &Event,
|
||||||
@@ -220,6 +224,15 @@ fn render_cpu(glyphs: &mut GlyphBrush<Resources, Factory>, cpu: &CPU, offset: [f
|
|||||||
color: color,
|
color: color,
|
||||||
..Section::default()
|
..Section::default()
|
||||||
});
|
});
|
||||||
|
position.0 += 16.0;
|
||||||
|
let color = FT_COLOR_WHITE;
|
||||||
|
glyphs.queue(Section {
|
||||||
|
text: &format!("{:#06x}", cpu.regs.flags),
|
||||||
|
scale: *FT_SCALE,
|
||||||
|
screen_position: position,
|
||||||
|
color: color,
|
||||||
|
..Section::default()
|
||||||
|
});
|
||||||
|
|
||||||
let cpu_register_texts = [
|
let cpu_register_texts = [
|
||||||
&format!("A: {0:#x} ({0})", cpu.regs.a),
|
&format!("A: {0:#x} ({0})", cpu.regs.a),
|
||||||
@@ -296,7 +309,7 @@ fn render_memory(glyphs: &mut GlyphBrush<Resources, Factory>, bus: &MemoryBus, o
|
|||||||
}
|
}
|
||||||
|
|
||||||
position_y.1 += FT_LINE_DISTANCE+FT_SIZE_PX * 1.5;
|
position_y.1 += FT_LINE_DISTANCE+FT_SIZE_PX * 1.5;
|
||||||
for page in (0x6000..0x60FF).step_by(16) {
|
for page in (0x2000..0x20FF).step_by(16) {
|
||||||
position_y.1 += FT_LINE_DISTANCE + FT_SIZE_PX;
|
position_y.1 += FT_LINE_DISTANCE + FT_SIZE_PX;
|
||||||
let mut line = format!("{:#06x}:", page);
|
let mut line = format!("{:#06x}:", page);
|
||||||
(0u16..16u16).map(|offset| offset + page)
|
(0u16..16u16).map(|offset| offset + page)
|
||||||
|
|||||||
@@ -44,14 +44,14 @@ pub trait Clockable {
|
|||||||
// A simple bus giving access to a chunk of memory
|
// A simple bus giving access to a chunk of memory
|
||||||
// and the cartrige
|
// and the cartrige
|
||||||
pub struct MemoryBus {
|
pub struct MemoryBus {
|
||||||
ram: [Byte; 0x07ff], // 2kb
|
ram: [Byte; 0x0800], // 2kb
|
||||||
cartrige: Option<Cartridge>
|
cartrige: Option<Cartridge>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemoryBus {
|
impl MemoryBus {
|
||||||
pub fn new() -> MemoryBus {
|
pub fn new() -> MemoryBus {
|
||||||
MemoryBus {
|
MemoryBus {
|
||||||
ram: [0; 0x07ff],
|
ram: [0; 0x0800],
|
||||||
cartrige: None,
|
cartrige: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,12 +65,12 @@ impl Memory for MemoryBus {
|
|||||||
|
|
||||||
fn readb(&self, addr: Addr) -> Byte {
|
fn readb(&self, addr: Addr) -> Byte {
|
||||||
if let Some(cartrige) = &self.cartrige {
|
if let Some(cartrige) = &self.cartrige {
|
||||||
if CART_ADDR_RANGE[0] <= addr && addr < CART_ADDR_RANGE[1] {
|
if CART_ADDR_RANGE[0] <= addr && addr <= CART_ADDR_RANGE[1] {
|
||||||
return cartrige.readb(addr)
|
return cartrige.readb(addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if RAM_ADDR_RANGE[0] <= addr && addr < RAM_ADDR_RANGE[1] {
|
if RAM_ADDR_RANGE[0] <= addr && addr <= RAM_ADDR_RANGE[1] {
|
||||||
// Ram is 3x mirrored after 07ff
|
// Ram is 3x mirrored after 07ff
|
||||||
return self.ram[(addr & 0x07ff) as usize]
|
return self.ram[(addr & 0x07ff) as usize]
|
||||||
}
|
}
|
||||||
@@ -79,12 +79,12 @@ impl Memory for MemoryBus {
|
|||||||
|
|
||||||
fn writeb(&mut self, addr: Addr, data: Byte) {
|
fn writeb(&mut self, addr: Addr, data: Byte) {
|
||||||
if let Some(cartrige) = &mut self.cartrige {
|
if let Some(cartrige) = &mut self.cartrige {
|
||||||
if CART_ADDR_RANGE[0] <= addr && addr < CART_ADDR_RANGE[1] {
|
if CART_ADDR_RANGE[0] <= addr && addr <= CART_ADDR_RANGE[1] {
|
||||||
cartrige.writeb(addr, data)
|
cartrige.writeb(addr, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if RAM_ADDR_RANGE[0] <= addr && addr < RAM_ADDR_RANGE[1] {
|
if RAM_ADDR_RANGE[0] <= addr && addr <= RAM_ADDR_RANGE[1] {
|
||||||
// Ram is 3x mirrored after 07ff
|
// Ram is 3x mirrored after 07ff
|
||||||
self.ram[(addr & 0x07ff) as usize] = data
|
self.ram[(addr & 0x07ff) as usize] = data
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ impl Cartridge {
|
|||||||
id => bail!("Mapper {:04} not supported", id)
|
id => bail!("Mapper {:04} not supported", id)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
debug!("Cartrige loaded. mapper: {:?}", &mapper);
|
||||||
Ok(Cartridge {
|
Ok(Cartridge {
|
||||||
prg_rom: prg_rom,
|
prg_rom: prg_rom,
|
||||||
chr_rom: chr_rom,
|
chr_rom: chr_rom,
|
||||||
|
|||||||
@@ -136,6 +136,11 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_flag_nz(&mut self, val: Byte) {
|
||||||
|
self.set_flag(ZERO, val == 0);
|
||||||
|
self.set_flag(NEGATIVE, (val & 0x80) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_flag(&self, flag: Byte) -> Byte {
|
pub fn get_flag(&self, flag: Byte) -> Byte {
|
||||||
if self.regs.flags & flag > 0 {
|
if self.regs.flags & flag > 0 {
|
||||||
1
|
1
|
||||||
@@ -340,9 +345,8 @@ impl CPU {
|
|||||||
let val = tmp2.0;
|
let val = tmp2.0;
|
||||||
let overflow = tmp1.1 || tmp2.1;
|
let overflow = tmp1.1 || tmp2.1;
|
||||||
self.set_flag(CARRY, (val & 0xFF) > 255);
|
self.set_flag(CARRY, (val & 0xFF) > 255);
|
||||||
self.set_flag(ZERO, val == 0);
|
|
||||||
self.set_flag(NEGATIVE, (val & 0x80) == 1);
|
|
||||||
self.set_flag(OVERFLOW, overflow);
|
self.set_flag(OVERFLOW, overflow);
|
||||||
|
self.set_flag_nz(val as Byte);
|
||||||
self.regs.a = val as Byte;
|
self.regs.a = val as Byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,25 +370,44 @@ impl CPU {
|
|||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_BIT<T: Memory>(&mut self, bus: &T, val: Word) {
|
// bits 7 and 6 of operand are transfered to bit 7 and 6 of SR (N,V);
|
||||||
unimplemented!()
|
// the zeroflag is set to the result of operand AND accumulator.
|
||||||
|
fn op_BIT<T: Memory>(&mut self, bus: &T, addr: Word) {
|
||||||
|
let val = self.readb(bus, addr);
|
||||||
|
self.set_flag(OVERFLOW, (val & OVERFLOW) == 1);
|
||||||
|
self.set_flag(NEGATIVE, (val & NEGATIVE) == 1);
|
||||||
|
println!("{:#06x}: {}", addr, val);
|
||||||
|
println!("{}", (val & self.regs.a));
|
||||||
|
self.set_flag(ZERO, (val & self.regs.a) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_BMI<T: Memory>(&mut self, bus: &T, val: Word) {
|
// Jump to address
|
||||||
unimplemented!()
|
fn jump(&mut self, addr: Addr) {
|
||||||
}
|
|
||||||
|
|
||||||
// Branch if 0 flag is set
|
|
||||||
fn op_BNE(&mut self, addr: Word) {
|
|
||||||
if self.get_flag(ZERO) == 0 {
|
|
||||||
let old_addr = self.regs.pc;
|
let old_addr = self.regs.pc;
|
||||||
self.regs.pc = addr;
|
self.regs.pc = addr;
|
||||||
println!("Jumping from {:#x} to {:#x}", old_addr, addr);
|
println!("Jumping from {:#x} to {:#x}", old_addr, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Branch if negative flag is set
|
||||||
|
fn op_BMI<T: Memory>(&mut self, bus: &T, addr: Addr) {
|
||||||
|
if self.get_flag(NEGATIVE) == 1 {
|
||||||
|
self.jump(addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_BPL<T: Memory>(&mut self, bus: &T, val: Word) {
|
// Branch if 0 flag is set
|
||||||
unimplemented!()
|
fn op_BNE(&mut self, addr: Addr) {
|
||||||
|
if self.get_flag(ZERO) == 0 {
|
||||||
|
self.jump(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Branch if negative flag is unset
|
||||||
|
fn op_BPL<T: Memory>(&mut self, bus: &T, addr: Addr) {
|
||||||
|
if self.get_flag(NEGATIVE) == 0 {
|
||||||
|
self.jump(addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_BRK<T: Memory>(&mut self, bus: &T, val: Word) {
|
fn op_BRK<T: Memory>(&mut self, bus: &T, val: Word) {
|
||||||
@@ -439,15 +462,13 @@ impl CPU {
|
|||||||
// Decrement X
|
// Decrement X
|
||||||
fn op_DEX(&mut self) {
|
fn op_DEX(&mut self) {
|
||||||
self.regs.x = self.regs.x.wrapping_sub(1);
|
self.regs.x = self.regs.x.wrapping_sub(1);
|
||||||
self.set_flag(ZERO, self.regs.x == 0);
|
self.set_flag_nz(self.regs.x);
|
||||||
self.set_flag(NEGATIVE, (self.regs.x & 0x80) != 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrement Y
|
// Decrement Y
|
||||||
fn op_DEY(&mut self) {
|
fn op_DEY(&mut self) {
|
||||||
self.regs.y = self.regs.y.wrapping_sub(1);
|
self.regs.y = self.regs.y.wrapping_sub(1);
|
||||||
self.set_flag(ZERO, self.regs.y == 0);
|
self.set_flag_nz(self.regs.y);
|
||||||
self.set_flag(NEGATIVE, (self.regs.y & 0x80) != 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_EOR<T: Memory>(&mut self, bus: &T, val: Word) {
|
fn op_EOR<T: Memory>(&mut self, bus: &T, val: Word) {
|
||||||
@@ -458,25 +479,22 @@ impl CPU {
|
|||||||
let val = self.readb(bus, addr);
|
let val = self.readb(bus, addr);
|
||||||
let val = val.wrapping_add(1);
|
let val = val.wrapping_add(1);
|
||||||
self.writeb(bus, addr, val);
|
self.writeb(bus, addr, val);
|
||||||
self.set_flag(ZERO, val == 0);
|
self.set_flag_nz(val);
|
||||||
self.set_flag(NEGATIVE, (val & 0x80) != 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_INX<T: Memory>(&mut self, bus: &T) {
|
fn op_INX<T: Memory>(&mut self, bus: &T) {
|
||||||
self.regs.x = self.regs.x.wrapping_add(1);
|
self.regs.x = self.regs.x.wrapping_add(1);
|
||||||
self.set_flag(ZERO, self.regs.x == 0);
|
self.set_flag_nz(self.regs.x);
|
||||||
self.set_flag(NEGATIVE, (self.regs.x & 0x80) != 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_INY<T: Memory>(&mut self, bus: &T) {
|
fn op_INY<T: Memory>(&mut self, bus: &T) {
|
||||||
self.regs.y = self.regs.y.wrapping_add(1);
|
self.regs.y = self.regs.y.wrapping_add(1);
|
||||||
self.set_flag(ZERO, self.regs.y == 0);
|
self.set_flag_nz(self.regs.y);
|
||||||
self.set_flag(NEGATIVE, (self.regs.y & 0x80) != 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jump to address (set pc)
|
// Jump to address (set pc)
|
||||||
fn op_JMP<T: Memory>(&mut self, bus: &T, addr: Word) {
|
fn op_JMP<T: Memory>(&mut self, bus: &T, addr: Word) {
|
||||||
self.regs.pc = addr;
|
self.jump(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jump to subroutine (leaves trace on the stack)
|
// Jump to subroutine (leaves trace on the stack)
|
||||||
@@ -486,31 +504,28 @@ impl CPU {
|
|||||||
self.regs.sp -= 1;
|
self.regs.sp -= 1;
|
||||||
bus.writeb(STACK_BASE_ADDR + self.regs.sp as Word, (self.regs.pc & 0x00ff) as Byte);
|
bus.writeb(STACK_BASE_ADDR + self.regs.sp as Word, (self.regs.pc & 0x00ff) as Byte);
|
||||||
self.regs.sp -= 1;
|
self.regs.sp -= 1;
|
||||||
self.regs.pc = addr;
|
self.jump(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read value from addr into A
|
// Read value from addr into A
|
||||||
fn op_LDA<T: Memory>(&mut self, bus: &T, addr: Word) {
|
fn op_LDA<T: Memory>(&mut self, bus: &T, addr: Word) {
|
||||||
let val = bus.readb(addr);
|
let val = bus.readb(addr);
|
||||||
self.regs.a = val;
|
self.regs.a = val;
|
||||||
self.set_flag(ZERO, val == 0);
|
self.set_flag_nz(val);
|
||||||
self.set_flag(NEGATIVE, (val & 0x80) != 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read value from addr into X
|
// Read value from addr into X
|
||||||
fn op_LDX<T: Memory>(&mut self, bus: &T, addr: Word) {
|
fn op_LDX<T: Memory>(&mut self, bus: &T, addr: Word) {
|
||||||
let val = bus.readb(addr);
|
let val = bus.readb(addr);
|
||||||
self.regs.x = val;
|
self.regs.x = val;
|
||||||
self.set_flag(ZERO, val == 0);
|
self.set_flag_nz(val);
|
||||||
self.set_flag(NEGATIVE, (val & 0x80) != 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read value from addr into Y
|
// Read value from addr into Y
|
||||||
fn op_LDY<T: Memory>(&mut self, bus: &T, addr: Word) {
|
fn op_LDY<T: Memory>(&mut self, bus: &T, addr: Word) {
|
||||||
let val = bus.readb(addr);
|
let val = bus.readb(addr);
|
||||||
self.regs.y = val;
|
self.regs.y = val;
|
||||||
self.set_flag(ZERO, val == 0);
|
self.set_flag_nz(val);
|
||||||
self.set_flag(NEGATIVE, (val & 0x80) != 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_LSR<T: Memory>(&mut self, bus: &T, val: Word) {
|
fn op_LSR<T: Memory>(&mut self, bus: &T, val: Word) {
|
||||||
@@ -521,8 +536,9 @@ impl CPU {
|
|||||||
// does nothing
|
// does nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_ORA<T: Memory>(&mut self, bus: &T, val: Word) {
|
fn op_ORA<T: Memory>(&mut self, bus: &T, addr: Addr) {
|
||||||
unimplemented!()
|
self.regs.a |= self.readb(bus, addr);
|
||||||
|
self.set_flag_nz(self.regs.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_PHA<T: Memory>(&mut self, bus: &T, val: Word) {
|
fn op_PHA<T: Memory>(&mut self, bus: &T, val: Word) {
|
||||||
@@ -564,7 +580,12 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn op_RTS<T: Memory>(&mut self, bus: &T, val: Word) {
|
fn op_RTS<T: Memory>(&mut self, bus: &T, val: Word) {
|
||||||
unimplemented!()
|
self.regs.sp += 1;
|
||||||
|
let lo = bus.readb(0x0100 + self.regs.sp as Addr);
|
||||||
|
self.regs.sp += 1;
|
||||||
|
let hi = bus.readb(0x0100 + self.regs.sp as Addr);
|
||||||
|
let addr = (hi as Addr) << 8 | lo as Addr;
|
||||||
|
self.regs.pc = addr + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_SBC<T: Memory>(&mut self, bus: &T, val: Word) {
|
fn op_SBC<T: Memory>(&mut self, bus: &T, val: Word) {
|
||||||
|
|||||||
@@ -20,16 +20,22 @@ impl Disasm {
|
|||||||
pub fn disassemble(mem: &MemoryBus, start: Addr, stop: Addr) -> Result<Self, Error> {
|
pub fn disassemble(mem: &MemoryBus, start: Addr, stop: Addr) -> Result<Self, Error> {
|
||||||
let mut instructions = Vec::new();
|
let mut instructions = Vec::new();
|
||||||
let mut addresses = Vec::new();
|
let mut addresses = Vec::new();
|
||||||
let mut mem_iter = ((start as usize) .. (stop as usize)+1).map({|a| a as Addr});
|
let mut mem_iter = ((start as usize) .. (stop as usize)).map({|a| a as Addr});
|
||||||
while let Some(addr) = mem_iter.next() {
|
while let Some(addr) = mem_iter.next() {
|
||||||
|
|
||||||
let opcode = mem.readb(addr);
|
let opcode = mem.readb(addr);
|
||||||
|
|
||||||
|
|
||||||
// Decode opcode, default to NOP/IMP to "skip" the byte
|
// Decode opcode, default to NOP/IMP to "skip" the byte
|
||||||
let i = Instruction::decode_op(opcode)
|
let i = Instruction::decode_op(opcode)
|
||||||
.unwrap_or(Instruction::decode_op(0xeau8).unwrap());
|
.unwrap_or(Instruction::decode_op(0xeau8).unwrap());
|
||||||
|
|
||||||
// debug!("{:?}", i);
|
// debug!("{:?}", i);
|
||||||
let args = match i.addr_mode {
|
let args = match i.addr_mode {
|
||||||
AddrMode::IMM => format!("#{0:02x} ({0})", mem.readb(mem_iter.next().unwrap())),
|
AddrMode::IMM => {
|
||||||
|
let val = mem.readb(mem_iter.next().unwrap());
|
||||||
|
format!("#{0:02x} ({0})", val)
|
||||||
|
},
|
||||||
AddrMode::ZP0 | AddrMode::ZPX | AddrMode::ZPY => {
|
AddrMode::ZP0 | AddrMode::ZPX | AddrMode::ZPY => {
|
||||||
let rel_addr = mem.readb(mem_iter.next().unwrap());
|
let rel_addr = mem.readb(mem_iter.next().unwrap());
|
||||||
format!("{:#04x}", rel_addr)
|
format!("{:#04x}", rel_addr)
|
||||||
@@ -58,9 +64,13 @@ impl Disasm {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let s = format!("{:#06x}: {} {} ({})", addr, i.operation, args, i.addr_mode);
|
let s = format!("{:#06x}: {} {} ({})", addr, i.operation, args, i.addr_mode);
|
||||||
// debug!("{:#06x} {}", addr, &s);
|
// println!("opcode: {:#04x} {:?}", opcode, i);
|
||||||
|
// println!("{}", &s);
|
||||||
|
|
||||||
instructions.push(s);
|
instructions.push(s);
|
||||||
addresses.push(addr);
|
addresses.push(addr);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Ok(Disasm { start, stop, instructions, addresses })
|
Ok(Disasm { start, stop, instructions, addresses })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ pub trait Mapper {
|
|||||||
// Cartrige:
|
// Cartrige:
|
||||||
// 0x4000-0xffff -> first 16K
|
// 0x4000-0xffff -> first 16K
|
||||||
// 0xc000-0xffff -> last 16K or mirror or 0x8000-0xbfff
|
// 0xc000-0xffff -> last 16K or mirror or 0x8000-0xbfff
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Mapper0 {
|
pub struct Mapper0 {
|
||||||
prg_banks: Byte,
|
prg_banks: Byte,
|
||||||
chr_banks: Byte,
|
chr_banks: Byte,
|
||||||
@@ -29,17 +30,23 @@ impl Mapper0 {
|
|||||||
|
|
||||||
impl Mapper for Mapper0 {
|
impl Mapper for Mapper0 {
|
||||||
fn map_read_addr(&self, addr: Addr) -> Addr {
|
fn map_read_addr(&self, addr: Addr) -> Addr {
|
||||||
|
if 0x8000 <= addr && addr <= 0xFFFF {
|
||||||
if self.prg_banks > 1 {
|
if self.prg_banks > 1 {
|
||||||
addr & 0x7fff
|
return addr & 0x7fff;
|
||||||
} else {
|
} else {
|
||||||
addr & 0x3fff
|
return addr & 0x3fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
0x0000
|
||||||
|
}
|
||||||
fn map_write_addr(&self, addr: Addr) -> Addr {
|
fn map_write_addr(&self, addr: Addr) -> Addr {
|
||||||
|
if 0x8000 <= addr && addr <= 0xFFFF {
|
||||||
if self.prg_banks > 1 {
|
if self.prg_banks > 1 {
|
||||||
addr & 0x7fff
|
return addr & 0x7fff;
|
||||||
} else {
|
} else {
|
||||||
addr & 0x3fff
|
return addr & 0x3fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
0x0000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user