Cleans up some files and adds the README files

master
Joey Pollack 1 year ago
parent 2964ff3b60
commit d27cd2c3e4

@ -1,5 +1,5 @@
# RE6502 # RE6502
RE6502 is an emulator for the 6502 cpu written in rust. The project comes with a very basic virtual machine for testing (it just has simple I/O functionality) as well as some test programs (find these in simple_test_machine/programs). The test programs can be built with the win2c64 (or lin2c64, or mac2c64) assembler which can be found here: https://www.aartbik.com/retro.php. Theoretically any 6502 assembler should work but win2c64 is the one I've been using for testing. RE6502 is an emulator for the 6502 cpu written in rust. The project comes with a very basic virtual machine for testing (it just has simple I/O functionality) as well as some test programs (find these in simple_test_machine/programs). The test programs can be built with the win2c64 (or lin2c64, or mac2c64) assembler which can be found here: https://www.aartbik.com/retro.php. Theoretically any 6502 assembler should work but win2c64 is the one I've been using for testing.
# Building # Building
The emulator doesn't really do anything on it's own but you can build it with the normal `cargo build` or `cargo run` if you run this program it will just do some simple internal tests. There are also unit tests you can run with `cargo test`. To make better use of the emulator you'll need to use it as a component of a larger emulator/vm. Take a look a the Simple Test Machine project to see how to use the RE6502 as a component.

@ -1,8 +1,18 @@
# The Simple Test Machine # The Simple Test Machine
The Simple Test Machine is a very basic virtual machine that uses the RE6502 as the cpu and a custom Console for simple I/O operations. There are example programs in the programs directory for reference/testing. The important memory addresses (I/O buffers, bit flags, etc) are listed in the src/machine.rs file.
# Running the Simple Test Machine # Running the Simple Test Machine
To build the project you can `cd simple_test_machine` then `cargo build` or `cargo run`. If you run it on it's own it will just run some basic internal test programs. To run a specific progam you can pass the name of the binary to load when the machine starts up. To do this with cargo try `cargo run -- path/to/the/program` (ex. `cargo run -- programs/bin/hello.rw`).
# Assembling Programs for the Simple Test Machine # Assembling Programs for the Simple Test Machine
Program binaries are not included in this repo but you can build them from the .asm files in the programs subdirectory. I've tested building these programs with the `win2c64` assembler (it also has linux `lin2c64` and mac `mac2c64` versions) that can be found here: https://www.aartbik.com/retro.php.
To use the assembler you can invoke it directly or use the `assemble.bat` script in the programs subdirectory.
## Using the assemble.bat script
To use the assemble.bat script you'll need to cd into the programs directory: `cd programs` (or, if you're in the project root: `cd simple_test_machine/programs`) then you can run the script with `.\assemble.bat hello.asm`. The script will move the resulting binary into the bin directory.
## Using win2c64 directly
You can invoke win2c64 directly with `win2c64.exe -R my_program.asm` The `-R` option is necessary to have the assembler output the binary in the correct format.

@ -1,6 +1,6 @@
; echo example - takes input and then prints it back out ; echo example - takes input and then prints it back out
; This is for testing the InputConsole of the Simple Test Machine ; This is for testing input of the Simple Test Machine
; by Joey Pollack ; by Joey Pollack
; assemble with win2c64 (or lin2c64, or mac2c64) using the -R option ; assemble with win2c64 (or lin2c64, or mac2c64) using the -R option
@ -12,7 +12,7 @@ con_out .equ $1100 ; console output buffer address
con_in .equ $1200 ; console input buffer address con_in .equ $1200 ; console input buffer address
con_flags .equ $009A ; console flags address con_flags .equ $009A ; console flags address
prt_str_flag .equ $0002 ; print string flag prt_str_flag .equ $0002 ; print string flag
prmp_input_flag .equ $0004 ; prompt for input flag prmp_input_flag .equ $0010 ; prompt for input flag
; MAIN ; MAIN
main .org $0200 ; program load address for the Simple Test Machine main .org $0200 ; program load address for the Simple Test Machine

@ -6,26 +6,30 @@
; Adapted for the RE6502 emulator simple test machine ; Adapted for the RE6502 emulator simple test machine
; compile with win2c64 using the -R option ; compile with win2c64 using the -R option
; This example shows how to print a string to the console
strout .equ $1100 ; console output address strout .equ $1100 ; console output address
con_flags .equ $009A ; console flags address con_flags .equ $009A ; console flags address
prt_str_flag .equ $0002 prt_str_flag .equ $0002 ; the print flag bitmask
main .org $0200 ; program load address for the simple test machine main .org $0200 ; program load address for the simple test machine
ldx #0
loop lda text,x ; Copy the string into the console output buffer
sta strout,x ldx #0 ; initialize the offset counter
inx loop lda text,x ; load byte from the text buffer, offset by x register
cpx #11 sta strout,x ; store byte into the output buffer, offset by x register
bne loop inx ; increment the offset counter
cpx #11 ; check if we've reached the end of the string - text is 11 bytes long
bne loop ; branch if we haven't reached the end yet
; null terminate the string ; null terminate the string
lda #0 lda #0
sta strout,x sta strout,x
; Set flag to do the print ; Set flag to do the print
lda con_flags lda con_flags ; load flags into accumulator
ora #prt_str_flag ora #prt_str_flag ; set the print string flag
sta con_flags ; 0x86, 0x9A, ; Print string flag is at 0x9A sta con_flags ; store flags back into memory - this will trigger the print
; End the program ; End the program
rts ; 0x60 rts ; 0x60

@ -10,22 +10,22 @@ prt_str_flag .equ $0001 ; print string flag
; FAST MULTIPLY program from: ; FAST MULTIPLY program from:
; http://6502.org/source/integers/fastx10.htm ; http://6502.org/source/integers/fastx10.htm
main LDA #7 ; load 7 into the accumulator main LDA #7 ; load 7 into the accumulator
ASL ;multiply by 2 ASL ; multiply by 2
STA TEMP ;temp store in TEMP STA TEMP ; temp store in TEMP
ASL ;again multiply by 2 (*4) ASL ; again multiply by 2 (*4)
ASL ;again multiply by 2 (*8) ASL ; again multiply by 2 (*8)
CLC CLC
ADC TEMP ;as result, A = x*8 + x*2 ADC TEMP ; as result, A = x*8 + x*2
; PRINT RESULT ; print result
STA strout ; store A into the console output address STA strout ; store A into the console output address
LDX #0 ; 0xA2, 0x00, ; null terminator LDX #0 ; 0xA2, 0x00, ; null terminator
STX strout+1 ; store null terminator to output addr + 1 STX strout+1 ; store null terminator to output addr + 1
; Set flag to do the print ; Set flag to do the print
LDA con_flags ; load the current console flag set LDA con_flags ; load the current console flag set
ORA #prt_str_flag ; turn on the print string flag ORA #prt_str_flag ; turn on the print string flag
STA con_flags ; store the flags back in memory STA con_flags ; store the flags back in memory
; End the program ; End the program
RTS ; 0x60 RTS ; 0x60

@ -1,29 +0,0 @@
; Multiply 7 with 10 and print the result
; For testing this program was assembled with c64 (using the -R option):
; https://www.aartbik.com/MISC/c64.html
; FAST MULTIPLY program from:
; http://6502.org/source/integers/fastx10.htm
main LDA #7 ; load 7 into the accumulator
ASL ;multiply by 2
STA TEMP ;temp store in TEMP
ASL ;again multiply by 2 (*4)
ASL ;again multiply by 2 (*8)
CLC
ADC TEMP ;as result, A = x*8 + x*2
; PRINT RESULT
STA $A0 ; 0x85, 0xA0, ; store A into the console output address
LDX #0 ; 0xA2, 0x00, ; null terminator
STX $A1 ; 0x86, 0xA1, ; store null terminator to output addr + 1
; Set flag to do the print
LDX #1 ; 0xA2, 0x01,
STX $9F ; 0x86, 0x9F, ; Print byte flag is at 0x9F
; End the program
RTS ; 0x60
; Variables
TEMP .byte 0

@ -3,25 +3,35 @@
use std::{io, str}; use std::{io, str};
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| //|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// MEMORY ADDRESSES AND FLAGS // MEMORY ADDRESSES AND FLAG MASKS
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| //|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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! // CPU Addresses
pub const INPUT_BUF_ADDR: u16 = 0x1200; // Input buffer const PROGRAM_START_ADDR: u16 = 0x0200; // Program code starts on page 2
pub const INPUT_BUF_SIZE: u16 = 0x00FF; // Input buffer is 255 bytes const CPU_RESET_START_ADDR: u16 = 0xFFFC; // This is where the cpu looks for the address to start executing code at
// Console Addresses
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 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. // Console Flag Masks
pub const READ_LINE_FLAG: u8 = 0x04; // Set this flag to request user input from the keyboard pub const PRINT_BYTE_FLAG: u8 = 0x01; // Trigger printing a single byte
pub const READ_OVERFLOW_FLAG: u8 = 0x08; // This flag is set after reading input if there is too much input for the buffer pub const PRINT_STR_FLAG: u8 = 0x02; // Trigger printing a string (continues printing bytes until a null byte is encountered)
pub const READ_LINE_FLAG: u8 = 0x10; // Set this flag to request user input from the keyboard
pub const READ_OVERFLOW_FLAG: u8 = 0x20; // This flag is set after reading input if there is too much input for the buffer
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// BUS // BUS
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
use re6502::r6502::{R6502, Bus, Flags}; use re6502::r6502::{R6502, Bus, Flags};
// The Bus is how you connect other components to the RE6502 cpu.
// At minimium the read() and write() traits must be implement for the Bus.
// The following is a very basic Test Bus implementation.
struct TBus struct TBus
{ {
memory: [u8; 64 * 1024] memory: [u8; 64 * 1024]
@ -129,9 +139,6 @@ impl Console
// Make sure the string will fit in the input buffer // Make sure the string will fit in the input buffer
if (buffer.len() + 1) as u16 >= INPUT_BUF_SIZE 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.
// reset the read flag and set the overflow flag // reset the read flag and set the overflow flag
value &= !(READ_LINE_FLAG); value &= !(READ_LINE_FLAG);
value |= READ_OVERFLOW_FLAG; value |= READ_OVERFLOW_FLAG;
@ -158,26 +165,10 @@ impl Console
} }
} }
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// CONSOLE INPUT
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
struct InputConsole {}
impl InputConsole
{
}
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// MACHINE // MACHINE
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
pub struct TestMachine pub struct TestMachine
{ {
bus: TBus, bus: TBus,

Loading…
Cancel
Save