|
|
|
@ -2,6 +2,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
use std::str;
|
|
|
|
use std::str;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
// USED MEMORY ADDRESSES
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
const PROGRAM_START_ADDR: u16 = 0x0200; // Program code starts on page 2
|
|
|
|
|
|
|
|
const CPU_RESET_START_ADDR: u16 = 0xFFFC; // This is where the cpu looks for the address to start executing code at
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub const OUTPUT_BUF_ADDR: u16 = 0x1100; // Output buffer -- Put values to be printed at this location!
|
|
|
|
|
|
|
|
pub const INPUT_BUF_ADDR: u16 = 0x1200; // Input buffer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub const CONSOLE_FLAGS_ADDR: u16 = 0x009A; // Grouping all of the console flags into a single byte
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub const PRINT_BYTE_FLAG: u8 = 0x01; // Then set one of these flags to trigger the print
|
|
|
|
|
|
|
|
pub const PRINT_STR_FLAG: u8 = 0x02; // and indicate what type is being printed.
|
|
|
|
|
|
|
|
pub const READ_KB_FLAG: u8 = 0x04; // Set this address to 1 to request user input from the keyboard
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
// BUS
|
|
|
|
// BUS
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
@ -49,12 +64,9 @@ impl Bus for TBus
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
// CONSOLE
|
|
|
|
// CONSOLE OUTPUT
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
pub const OUTPUT_ADDR: u16 = 0x00A0; // Put values to be printed at this location!
|
|
|
|
|
|
|
|
pub const PRINT_BYTE_FLAG: u16 = 0x009F; // Then set one of these flags to trigger the print
|
|
|
|
|
|
|
|
pub const PRINT_STR_FLAG: u16 = 0x009E; // and indicate what type is being printed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct OutputConsole
|
|
|
|
struct OutputConsole
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -71,43 +83,66 @@ impl OutputConsole
|
|
|
|
fn clock(_cpu: &mut R6502, bus: &mut TBus )
|
|
|
|
fn clock(_cpu: &mut R6502, bus: &mut TBus )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Check for a string to print
|
|
|
|
// Check for a string to print
|
|
|
|
let mut value = bus.read(PRINT_STR_FLAG);
|
|
|
|
let mut value = bus.read(CONSOLE_FLAGS_ADDR);
|
|
|
|
if value != 0
|
|
|
|
if (value & PRINT_STR_FLAG) != 0
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let mut msg: Vec<u8> = Vec::new();
|
|
|
|
let mut msg: Vec<u8> = Vec::new();
|
|
|
|
|
|
|
|
|
|
|
|
let mut idx = 0;
|
|
|
|
let mut idx = 0;
|
|
|
|
while value != 0
|
|
|
|
while value != 0
|
|
|
|
{
|
|
|
|
{
|
|
|
|
value = bus.read(OUTPUT_ADDR + idx);
|
|
|
|
value = bus.read(OUTPUT_BUF_ADDR + idx);
|
|
|
|
msg.push(value);
|
|
|
|
msg.push(value);
|
|
|
|
idx += 1;
|
|
|
|
idx += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Mark the string as empty again
|
|
|
|
// Mark the string as empty again
|
|
|
|
bus.write(PRINT_STR_FLAG, 0);
|
|
|
|
value &= !(PRINT_STR_FLAG);
|
|
|
|
|
|
|
|
bus.write(CONSOLE_FLAGS_ADDR, value);
|
|
|
|
|
|
|
|
|
|
|
|
println!("{}", str::from_utf8(&msg).unwrap());
|
|
|
|
println!("{}", str::from_utf8(&msg).unwrap());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check for byte to print
|
|
|
|
// Check for byte to print
|
|
|
|
let flag = bus.read(PRINT_BYTE_FLAG);
|
|
|
|
let mut flag = bus.read(CONSOLE_FLAGS_ADDR);
|
|
|
|
if flag != 0
|
|
|
|
if (flag & PRINT_BYTE_FLAG)!= 0
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let byte = bus.read(OUTPUT_ADDR);
|
|
|
|
// read the byte
|
|
|
|
bus.write(PRINT_BYTE_FLAG, 0);
|
|
|
|
let byte = bus.read(OUTPUT_BUF_ADDR);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// reset the flag
|
|
|
|
|
|
|
|
flag &= !(PRINT_BYTE_FLAG);
|
|
|
|
|
|
|
|
bus.write(CONSOLE_FLAGS_ADDR, flag);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// print the byte
|
|
|
|
println!("{}", byte as u8);
|
|
|
|
println!("{}", byte as u8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
// CONSOLE INPUT
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct InputConsole {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl InputConsole
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
fn clock(_cpu: &mut R6502, bus: &mut TBus)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
// MACHINE
|
|
|
|
// MACHINE
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
const PROGRAM_START_ADDR: u16 = 0x0200; // Program code starts on page 2
|
|
|
|
|
|
|
|
const CPU_RESET_START_ADDR: u16 = 0xFFFC; // This is where the cpu looks for the address to start executing code at
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub struct TestMachine
|
|
|
|
pub struct TestMachine
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -150,6 +185,10 @@ impl TestMachine
|
|
|
|
{
|
|
|
|
{
|
|
|
|
self.cpu.clock(&mut self.bus);
|
|
|
|
self.cpu.clock(&mut self.bus);
|
|
|
|
OutputConsole::clock(&mut self.cpu, &mut self.bus);
|
|
|
|
OutputConsole::clock(&mut self.cpu, &mut self.bus);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Check if the input flag is set (need to choose a memory location for it)
|
|
|
|
|
|
|
|
// if it's set, prompt for input and copy the input into memory (need an address for that too)
|
|
|
|
|
|
|
|
// ACTUALLY: Move that logic into a new module (InputConsole) and just call clock() (like OutputConsole)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|