simple addition working

master
Joey Pollack 2 years ago
parent 8f3429dcc8
commit 99ff781d3d

@ -42,11 +42,63 @@ fn main()
cpu.clear_flag(Flags::I); cpu.clear_flag(Flags::I);
println!("\nI Flag is: {}", cpu.check_flag(Flags::I)); println!("\nI Flag is: {}", cpu.check_flag(Flags::I));
// run_simple_or_program(&mut cpu);
run_addition_test(&mut cpu);
println!("\nFinished.");
}
fn run_addition_test(cpu: &mut R6502)
{
println!("\nRunning a simple addition test with no overflow or carry: 8 + 23");
//////////////////////////////////
// Setup Bus with program address
//////////////////////////////////
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
///////////////////////////////
// write the program to memory
//////////////////////////////
// LDA #8
bus.write(addr, 0xA9); // LDA - Immediate mode
bus.write(addr + 1, 0x08); // Argument
// ADC #17 [23 dec]
bus.write(addr + 2, 0x69); // ADC - Immediate mode
bus.write(addr + 3, 0x17); // Argument
////////////////////
// Run the program!
////////////////////
// Restart cpu
cpu.reset(&mut bus);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
cpu.clock(&mut bus);
println!("\nProgram result, A register: {}", cpu.a);
}
fn run_simple_or_program(cpu: &mut R6502)
{
println!("\nRunning a very simple test program:\n\tLDA #9\n\tORA #2\n Result should be 11 in the A register"); println!("\nRunning a very simple test program:\n\tLDA #9\n\tORA #2\n Result should be 11 in the A register");
////////////////////////// //////////////////////////////////
// Setup Bus with program // Setup Bus with program address
////////////////////////// //////////////////////////////////
let mut bus = RAMBus::new(); let mut bus = RAMBus::new();
@ -81,6 +133,4 @@ fn main()
cpu.clock(&mut bus); cpu.clock(&mut bus);
println!("\nProgram result, A register: {}", cpu.a); println!("\nProgram result, A register: {}", cpu.a);
}
println!("\nFinished.");
}

@ -0,0 +1,37 @@
The code in the methods r6502::instructions::ADC and r6502::instructions::SDC
is adapted from code written by javidx9 (David Barr) and is subject to the following license:
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2018-2019 OneLoneCoder.com
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions or derivations of source code must retain the above
copyright notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce
the above copyright notice. This list of conditions and the following
disclaimer must be reproduced in the documentation and/or other
materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@ -3,6 +3,8 @@
use super::{R6502, Bus}; use super::{R6502, Bus};
// Instruction decoding:
// https://llx.com/Neil/a2/opcodes.html
// GROUP ONE ADDRESS MODES // GROUP ONE ADDRESS MODES
// 000 (zero page,X) IZX // 000 (zero page,X) IZX
@ -38,6 +40,7 @@ impl AddressingModes
} }
impl AddressingModes impl AddressingModes
{ {
// This is also the accumulator mode // This is also the accumulator mode

@ -4,20 +4,8 @@
use super::{R6502, Bus, Flags}; use super::{R6502, Bus, Flags};
// uint8_t ADC(); uint8_t AND(); uint8_t ASL(); uint8_t BCC(); // Instruction decoding:
// uint8_t BCS(); uint8_t BEQ(); uint8_t BIT(); uint8_t BMI(); // https://llx.com/Neil/a2/opcodes.html
// uint8_t BNE(); uint8_t BPL(); uint8_t BRK(); uint8_t BVC();
// uint8_t BVS(); uint8_t CLC(); uint8_t CLD(); uint8_t CLI();
// uint8_t CLV(); uint8_t CMP(); uint8_t CPX(); uint8_t CPY();
// uint8_t DEC(); uint8_t DEX(); uint8_t DEY(); uint8_t EOR();
// uint8_t INC(); uint8_t INX(); uint8_t INY(); uint8_t JMP();
// uint8_t JSR(); uint8_t LDA(); uint8_t LDX(); uint8_t LDY();
// uint8_t LSR(); uint8_t NOP(); uint8_t ORA(); uint8_t PHA();
// uint8_t PHP(); uint8_t PLA(); uint8_t PLP(); uint8_t ROL();
// uint8_t ROR(); uint8_t RTI(); uint8_t RTS(); uint8_t SBC();
// uint8_t SEC(); uint8_t SED(); uint8_t SEI(); uint8_t STA();
// uint8_t STX(); uint8_t STY(); uint8_t TAX(); uint8_t TAY();
// uint8_t TSX(); uint8_t TXA(); uint8_t TXS(); uint8_t TYA();
// GROUP ONE // GROUP ONE
// 000 ORA // 000 ORA
@ -65,17 +53,64 @@ impl Instructions
pub fn AND(cpu: &mut R6502, bus: &mut dyn Bus) pub fn AND(cpu: &mut R6502, bus: &mut dyn Bus)
{ {
cpu.a = cpu.a & cpu.working_data;
if cpu.a == 0
{
cpu.set_flag(Flags::Z);
}
if cpu.a & 0x80 != 0
{
cpu.set_flag(Flags::N);
}
} }
pub fn EOR(cpu: &mut R6502, bus: &mut dyn Bus) pub fn EOR(cpu: &mut R6502, bus: &mut dyn Bus)
{ {
cpu.a = cpu.a ^ cpu.working_data;
if cpu.a == 0
{
cpu.set_flag(Flags::Z);
}
if cpu.a & 0x80 != 0
{
cpu.set_flag(Flags::N);
}
} }
// Using a technique written javidx9
// The code in this function falls under the License (OLC-3) SEE LICENSE FILE
// https://github.com/OneLoneCoder/olcNES/blob/master/Part%232%20-%20CPU/olc6502.cpp#L659
pub fn ADC(cpu: &mut R6502, bus: &mut dyn Bus) pub fn ADC(cpu: &mut R6502, bus: &mut dyn Bus)
{ {
// 16 bit addition to capture the carry easier
let temp: u16 = cpu.a as u16 + cpu.working_data as u16;
if temp > 255
{
cpu.set_flag(Flags::C);
}
if temp == 0
{
cpu.set_flag(Flags::Z);
}
let did_overflow = (!((cpu.a as u16) ^ (cpu.working_data as u16)) & ((cpu.a as u16) ^ temp)) & 0x0080;
cpu.clear_flag(Flags::V);
if did_overflow > 0
{
cpu.set_flag(Flags::V);
}
cpu.clear_flag(Flags::N);
if temp & 0x80 > 0
{
cpu.set_flag(Flags::N);
}
cpu.a = (temp & 0x00FF) as u8;
} }
pub fn STA(cpu: &mut R6502, bus: &mut dyn Bus) pub fn STA(cpu: &mut R6502, bus: &mut dyn Bus)

@ -127,7 +127,9 @@ impl R6502
fn execute(instruction: u8, cpu: &mut R6502, bus: &mut dyn Bus) fn execute(instruction: u8, cpu: &mut R6502, bus: &mut dyn Bus)
{ {
// Instruction decoding:
// https://llx.com/Neil/a2/opcodes.html
let group_code = instruction & 0x03; // group one has a bit pattern of xxxxxx01 let group_code = instruction & 0x03; // group one has a bit pattern of xxxxxx01
match group_code match group_code
{ {

@ -1,6 +1,8 @@
General: General:
☐ Fully implement clock cycle tracking ☐ Fully implement clock cycle tracking
☐ Add a disassembler for debugging
☐ Debug data lookup for instructions
Addressing modes: Addressing modes:
☐ IMP - Implied ☐ IMP - Implied

Loading…
Cancel
Save