From 84c18afd0910a427d00e6572957cd3d48be1ad5b Mon Sep 17 00:00:00 2001 From: Joey Pollack Date: Wed, 3 Jul 2024 17:28:28 -0400 Subject: [PATCH] Adds the InputConsole and a test program for it - echo.asm --- .vscode/launch.json | 2 +- simple_test_machine/programs/echo.asm | 57 +++++++++++++++++++++++++++ simple_test_machine/src/machine.rs | 49 +++++++++++++++++------ 3 files changed, 96 insertions(+), 12 deletions(-) create mode 100644 simple_test_machine/programs/echo.asm diff --git a/.vscode/launch.json b/.vscode/launch.json index e23cc42..106d48e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -60,7 +60,7 @@ "kind": "bin" } }, - "args": ["simple_test_machine\\programs\\hello.rw"], + "args": ["simple_test_machine\\programs\\echo.rw"], "cwd": "${workspaceFolder}" }, ] diff --git a/simple_test_machine/programs/echo.asm b/simple_test_machine/programs/echo.asm new file mode 100644 index 0000000..779d64b --- /dev/null +++ b/simple_test_machine/programs/echo.asm @@ -0,0 +1,57 @@ + +; echo example - takes input and then prints it back out +; This is for testing the InputConsole of the Simple Test Machine +; by Joey Pollack + +; assemble with win2c64 (or lin2c64, or mac2c64) using the -R option +; win2c64 found here: +; https://www.aartbik.com/retro.php + +; CONSTANTS +con_out .equ $1100 ; console output buffer address +con_in .equ $1200 ; console input buffer address +con_flags .equ $009A ; console flags address +prt_str_flag .equ $0002 ; print string flag +prmp_input_flag .equ $0004 ; prompt for input flag + +; MAIN +main .org $0200 ; program load address for the Simple Test Machine + ldx #0 +loop lda text,x + sta con_out,x + inx + cpx #12 ; length of text + bne loop + + ; null terminate the string + lda #0 + sta con_out,x + + ; Print the prompt message + lda con_flags ; load the console flags + ora #prt_str_flag ; set the print string flag + sta con_flags ; store the modified flags + + ; Prompt the user for input + lda con_flags ; load the console flags + ora #prmp_input_flag ; set the prompt for input flag + sta con_flags ; store the flags back to memory - this should trigger reading input + + ; Echo the input back to the console + ; iterate the input buffer and move each byte to the output buffer + ldx #0 ; initialize the offset counter +loop2 lda con_in,x ; load byte from the input buffer, offset by x register + sta con_out,x ; store byte into output buffer, offset by x register + inx ; increment the offset + cmp #0 ; check for the null byte + bne loop2 ; branch back to loop2 if we are not at the null byte yet + + lda con_flags ; load the console flags + ora #prt_str_flag ; set the print string flag + sta con_flags ; store the modified flags + + ; End the program + rts ; 0x60 + +; MEMORY +text .byte "Enter Text: " \ No newline at end of file diff --git a/simple_test_machine/src/machine.rs b/simple_test_machine/src/machine.rs index 75a24ca..16aea06 100644 --- a/simple_test_machine/src/machine.rs +++ b/simple_test_machine/src/machine.rs @@ -1,21 +1,22 @@ -use std::str; +use std::{io, str}; //||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -// USED MEMORY ADDRESSES +// MEMORY ADDRESSES AND FLAGS //||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 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 INPUT_BUF_SIZE: u16 = 0x00FF; // Input buffer is 255 bytes 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 +pub const READ_LINE_FLAG: u8 = 0x04; // Set this flag to request user input from the keyboard ///////////////////////////////////////////////////////////////////// // BUS @@ -104,15 +105,14 @@ impl OutputConsole } // Check for byte to print - let mut flag = bus.read(CONSOLE_FLAGS_ADDR); - if (flag & PRINT_BYTE_FLAG)!= 0 + else if (value & PRINT_BYTE_FLAG)!= 0 { // read the byte let byte = bus.read(OUTPUT_BUF_ADDR); // reset the flag - flag &= !(PRINT_BYTE_FLAG); - bus.write(CONSOLE_FLAGS_ADDR, flag); + value &= !(PRINT_BYTE_FLAG); + bus.write(CONSOLE_FLAGS_ADDR, value); // print the byte println!("{}", byte as u8); @@ -132,7 +132,37 @@ impl InputConsole { fn clock(_cpu: &mut R6502, bus: &mut TBus) { + // Check input request flag + let mut value = bus.read(CONSOLE_FLAGS_ADDR); + if (value & READ_LINE_FLAG) != 0 + { + let mut buffer = String::new(); + let stdin = io::stdin(); + stdin.read_line(&mut buffer).expect("Failed to read input from the console"); + + // Make sure the string will fit in the input buffer + if (buffer.len() + 1) as u16 >= INPUT_BUF_SIZE + { + // TODO: Change this to set an error flag instead of printing. This way + // the program can detect and handle these errors. + println!("ERROR: InputConsole cannot store input string into memory, string is too large"); + return; + } + // Store input in the input buffer + for (i, byte) in buffer.chars().enumerate() + { + bus.write(INPUT_BUF_ADDR + (i as u16), byte as u8); + } + + // Add the null byte to the end + bus.write(INPUT_BUF_ADDR + buffer.len() as u16, 0); + + // reset the flag + value &= !(READ_LINE_FLAG); + bus.write(CONSOLE_FLAGS_ADDR, value); + + } } } @@ -185,10 +215,7 @@ impl TestMachine { self.cpu.clock(&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) + InputConsole::clock(&mut self.cpu, &mut self.bus); } } } \ No newline at end of file