mirror of
https://github.com/DavidBuchanan314/6502-emu.git
synced 2024-06-07 02:29:34 +00:00
Made variable names slightly more consistent
This commit is contained in:
parent
12f80f409c
commit
1da995b11a
14
6502-emu.c
14
6502-emu.c
|
@ -6,7 +6,7 @@
|
||||||
#include "6502.h"
|
#include "6502.h"
|
||||||
#include "6850.h"
|
#include "6850.h"
|
||||||
|
|
||||||
struct termios oldTermios;
|
struct termios initial_termios;
|
||||||
|
|
||||||
void step_delay()
|
void step_delay()
|
||||||
{
|
{
|
||||||
|
@ -32,17 +32,17 @@ void run_cpu()
|
||||||
|
|
||||||
void restore_stdin()
|
void restore_stdin()
|
||||||
{
|
{
|
||||||
tcsetattr(0, TCSANOW, &oldTermios);
|
tcsetattr(0, TCSANOW, &initial_termios);
|
||||||
}
|
}
|
||||||
|
|
||||||
void raw_stdin()
|
void raw_stdin()
|
||||||
{
|
{
|
||||||
struct termios newTermios;
|
struct termios new_termios;
|
||||||
|
|
||||||
tcgetattr(0, &oldTermios);
|
tcgetattr(0, &initial_termios);
|
||||||
newTermios = oldTermios;
|
new_termios = initial_termios;
|
||||||
cfmakeraw(&newTermios);
|
cfmakeraw(&new_termios);
|
||||||
tcsetattr(0, TCSANOW, &newTermios);
|
tcsetattr(0, TCSANOW, &new_termios);
|
||||||
atexit(restore_stdin);
|
atexit(restore_stdin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
120
6502.c
120
6502.c
|
@ -14,12 +14,12 @@ int jumping; // used to check that we don't need to increment the PC after a jum
|
||||||
|
|
||||||
/* Flag Checks */
|
/* Flag Checks */
|
||||||
|
|
||||||
static inline void Nflag(int8_t val)
|
static inline void N_flag(int8_t val)
|
||||||
{
|
{
|
||||||
SR.bits.sign = val < 0;
|
SR.bits.sign = val < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void Zflag(uint8_t val)
|
static inline void Z_flag(uint8_t val)
|
||||||
{
|
{
|
||||||
SR.bits.zero = val == 0;
|
SR.bits.zero = val == 0;
|
||||||
}
|
}
|
||||||
|
@ -40,12 +40,12 @@ static inline uint8_t stack_pull()
|
||||||
|
|
||||||
static inline uint8_t * read_ptr()
|
static inline uint8_t * read_ptr()
|
||||||
{
|
{
|
||||||
return readAddr = get_ptr[inst.mode]();
|
return read_addr = get_ptr[inst.mode]();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint8_t * write_ptr()
|
static inline uint8_t * write_ptr()
|
||||||
{
|
{
|
||||||
return writeAddr = get_ptr[inst.mode]();
|
return write_addr = get_ptr[inst.mode]();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Instruction Implementations */
|
/* Instruction Implementations */
|
||||||
|
@ -57,15 +57,15 @@ static void inst_ADC()
|
||||||
SR.bits.carry = tmp > 0xFF;
|
SR.bits.carry = tmp > 0xFF;
|
||||||
SR.bits.overflow = ((A^tmp)&(operand^tmp)&0x80) != 0;
|
SR.bits.overflow = ((A^tmp)&(operand^tmp)&0x80) != 0;
|
||||||
A = tmp & 0xFF;
|
A = tmp & 0xFF;
|
||||||
Nflag(A);
|
N_flag(A);
|
||||||
Zflag(A);
|
Z_flag(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_AND()
|
static void inst_AND()
|
||||||
{
|
{
|
||||||
A &= * read_ptr();
|
A &= * read_ptr();
|
||||||
Nflag(A);
|
N_flag(A);
|
||||||
Zflag(A);
|
Z_flag(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_ASL()
|
static void inst_ASL()
|
||||||
|
@ -73,8 +73,8 @@ static void inst_ASL()
|
||||||
uint8_t tmp = * read_ptr();
|
uint8_t tmp = * read_ptr();
|
||||||
SR.bits.carry = (tmp & 0x80) != 0;
|
SR.bits.carry = (tmp & 0x80) != 0;
|
||||||
tmp <<= 1;
|
tmp <<= 1;
|
||||||
Nflag(tmp);
|
N_flag(tmp);
|
||||||
Zflag(tmp);
|
Z_flag(tmp);
|
||||||
* write_ptr() = tmp;
|
* write_ptr() = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,8 +102,8 @@ static void inst_BEQ()
|
||||||
static void inst_BIT()
|
static void inst_BIT()
|
||||||
{
|
{
|
||||||
uint8_t tmp = * read_ptr();
|
uint8_t tmp = * read_ptr();
|
||||||
Nflag(tmp);
|
N_flag(tmp);
|
||||||
Zflag(tmp & A);
|
Z_flag(tmp & A);
|
||||||
SR.bits.overflow = (tmp & 0x40) != 0;
|
SR.bits.overflow = (tmp & 0x40) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,8 +180,8 @@ static void inst_CMP()
|
||||||
{
|
{
|
||||||
uint8_t operand = * read_ptr();
|
uint8_t operand = * read_ptr();
|
||||||
uint8_t tmpDiff = A - operand;
|
uint8_t tmpDiff = A - operand;
|
||||||
Nflag(tmpDiff);
|
N_flag(tmpDiff);
|
||||||
Zflag(tmpDiff);
|
Z_flag(tmpDiff);
|
||||||
SR.bits.carry = A >= operand;
|
SR.bits.carry = A >= operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,8 +189,8 @@ static void inst_CPX()
|
||||||
{
|
{
|
||||||
uint8_t operand = * read_ptr();
|
uint8_t operand = * read_ptr();
|
||||||
uint8_t tmpDiff = X - operand;
|
uint8_t tmpDiff = X - operand;
|
||||||
Nflag(tmpDiff);
|
N_flag(tmpDiff);
|
||||||
Zflag(tmpDiff);
|
Z_flag(tmpDiff);
|
||||||
SR.bits.carry = X >= operand;
|
SR.bits.carry = X >= operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,8 +198,8 @@ static void inst_CPY()
|
||||||
{
|
{
|
||||||
uint8_t operand = * read_ptr();
|
uint8_t operand = * read_ptr();
|
||||||
uint8_t tmpDiff = Y - operand;
|
uint8_t tmpDiff = Y - operand;
|
||||||
Nflag(tmpDiff);
|
N_flag(tmpDiff);
|
||||||
Zflag(tmpDiff);
|
Z_flag(tmpDiff);
|
||||||
SR.bits.carry = Y >= operand;
|
SR.bits.carry = Y >= operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,53 +207,53 @@ static void inst_DEC()
|
||||||
{
|
{
|
||||||
uint8_t tmp = * read_ptr();
|
uint8_t tmp = * read_ptr();
|
||||||
tmp--;
|
tmp--;
|
||||||
Nflag(tmp);
|
N_flag(tmp);
|
||||||
Zflag(tmp);
|
Z_flag(tmp);
|
||||||
* write_ptr() = tmp;
|
* write_ptr() = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_DEX()
|
static void inst_DEX()
|
||||||
{
|
{
|
||||||
X--;
|
X--;
|
||||||
Nflag(X);
|
N_flag(X);
|
||||||
Zflag(X);
|
Z_flag(X);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_DEY()
|
static void inst_DEY()
|
||||||
{
|
{
|
||||||
Y--;
|
Y--;
|
||||||
Nflag(Y);
|
N_flag(Y);
|
||||||
Zflag(Y);
|
Z_flag(Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_EOR()
|
static void inst_EOR()
|
||||||
{
|
{
|
||||||
A ^= * read_ptr();
|
A ^= * read_ptr();
|
||||||
Nflag(A);
|
N_flag(A);
|
||||||
Zflag(A);
|
Z_flag(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_INC()
|
static void inst_INC()
|
||||||
{
|
{
|
||||||
uint8_t tmp = * read_ptr();
|
uint8_t tmp = * read_ptr();
|
||||||
tmp++;
|
tmp++;
|
||||||
Nflag(tmp);
|
N_flag(tmp);
|
||||||
Zflag(tmp);
|
Z_flag(tmp);
|
||||||
* write_ptr() = tmp;
|
* write_ptr() = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_INX()
|
static void inst_INX()
|
||||||
{
|
{
|
||||||
X++;
|
X++;
|
||||||
Nflag(X);
|
N_flag(X);
|
||||||
Zflag(X);
|
Z_flag(X);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_INY()
|
static void inst_INY()
|
||||||
{
|
{
|
||||||
Y++;
|
Y++;
|
||||||
Nflag(Y);
|
N_flag(Y);
|
||||||
Zflag(Y);
|
Z_flag(Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_JMP()
|
static void inst_JMP()
|
||||||
|
@ -275,22 +275,22 @@ static void inst_JSR()
|
||||||
static void inst_LDA()
|
static void inst_LDA()
|
||||||
{
|
{
|
||||||
A = * read_ptr();
|
A = * read_ptr();
|
||||||
Nflag(A);
|
N_flag(A);
|
||||||
Zflag(A);
|
Z_flag(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_LDX()
|
static void inst_LDX()
|
||||||
{
|
{
|
||||||
X = * read_ptr();
|
X = * read_ptr();
|
||||||
Nflag(X);
|
N_flag(X);
|
||||||
Zflag(X);
|
Z_flag(X);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_LDY()
|
static void inst_LDY()
|
||||||
{
|
{
|
||||||
Y = * read_ptr();
|
Y = * read_ptr();
|
||||||
Nflag(Y);
|
N_flag(Y);
|
||||||
Zflag(Y);
|
Z_flag(Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_LSR()
|
static void inst_LSR()
|
||||||
|
@ -298,8 +298,8 @@ static void inst_LSR()
|
||||||
uint8_t tmp = * read_ptr();
|
uint8_t tmp = * read_ptr();
|
||||||
SR.bits.carry = tmp & 1;
|
SR.bits.carry = tmp & 1;
|
||||||
tmp >>= 1;
|
tmp >>= 1;
|
||||||
Nflag(tmp);
|
N_flag(tmp);
|
||||||
Zflag(tmp);
|
Z_flag(tmp);
|
||||||
* write_ptr() = tmp;
|
* write_ptr() = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,8 +311,8 @@ static void inst_NOP()
|
||||||
static void inst_ORA()
|
static void inst_ORA()
|
||||||
{
|
{
|
||||||
A |= * read_ptr();
|
A |= * read_ptr();
|
||||||
Nflag(A);
|
N_flag(A);
|
||||||
Zflag(A);
|
Z_flag(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_PHA()
|
static void inst_PHA()
|
||||||
|
@ -329,8 +329,8 @@ static void inst_PHP()
|
||||||
static void inst_PLA()
|
static void inst_PLA()
|
||||||
{
|
{
|
||||||
A = stack_pull();
|
A = stack_pull();
|
||||||
Nflag(A);
|
N_flag(A);
|
||||||
Zflag(A);
|
Z_flag(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_PLP()
|
static void inst_PLP()
|
||||||
|
@ -345,8 +345,8 @@ static void inst_ROL()
|
||||||
tmp |= SR.bits.carry & 1;
|
tmp |= SR.bits.carry & 1;
|
||||||
SR.bits.carry = tmp > 0xFF;
|
SR.bits.carry = tmp > 0xFF;
|
||||||
tmp &= 0xFF;
|
tmp &= 0xFF;
|
||||||
Nflag(tmp);
|
N_flag(tmp);
|
||||||
Zflag(tmp);
|
Z_flag(tmp);
|
||||||
* write_ptr() = tmp;
|
* write_ptr() = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,8 +356,8 @@ static void inst_ROR()
|
||||||
tmp |= SR.bits.carry << 8;
|
tmp |= SR.bits.carry << 8;
|
||||||
SR.bits.carry = tmp & 1;
|
SR.bits.carry = tmp & 1;
|
||||||
tmp >>= 1;
|
tmp >>= 1;
|
||||||
Nflag(tmp);
|
N_flag(tmp);
|
||||||
Zflag(tmp);
|
Z_flag(tmp);
|
||||||
* write_ptr() = tmp;
|
* write_ptr() = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,8 +386,8 @@ static void inst_SBC()
|
||||||
SR.bits.carry = tmp > 0xFF;
|
SR.bits.carry = tmp > 0xFF;
|
||||||
SR.bits.overflow = ((A^tmp)&(operand^tmp)&0x80) != 0;
|
SR.bits.overflow = ((A^tmp)&(operand^tmp)&0x80) != 0;
|
||||||
A = tmp & 0xFF;
|
A = tmp & 0xFF;
|
||||||
Nflag(A);
|
N_flag(A);
|
||||||
Zflag(A);
|
Z_flag(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_SEC()
|
static void inst_SEC()
|
||||||
|
@ -424,29 +424,29 @@ static void inst_STY()
|
||||||
static void inst_TAX()
|
static void inst_TAX()
|
||||||
{
|
{
|
||||||
X = A;
|
X = A;
|
||||||
Nflag(X);
|
N_flag(X);
|
||||||
Zflag(X);
|
Z_flag(X);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_TAY()
|
static void inst_TAY()
|
||||||
{
|
{
|
||||||
Y = A;
|
Y = A;
|
||||||
Nflag(Y);
|
N_flag(Y);
|
||||||
Zflag(Y);
|
Z_flag(Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_TSX()
|
static void inst_TSX()
|
||||||
{
|
{
|
||||||
X = SP;
|
X = SP;
|
||||||
Nflag(X);
|
N_flag(X);
|
||||||
Zflag(X);
|
Z_flag(X);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_TXA()
|
static void inst_TXA()
|
||||||
{
|
{
|
||||||
A = X;
|
A = X;
|
||||||
Nflag(A);
|
N_flag(A);
|
||||||
Zflag(A);
|
Z_flag(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inst_TXS()
|
static void inst_TXS()
|
||||||
|
@ -457,8 +457,8 @@ static void inst_TXS()
|
||||||
static void inst_TYA()
|
static void inst_TYA()
|
||||||
{
|
{
|
||||||
A = Y;
|
A = Y;
|
||||||
Nflag(A);
|
N_flag(A);
|
||||||
Zflag(A);
|
Z_flag(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Addressing Implementations */
|
/* Addressing Implementations */
|
||||||
|
|
4
6502.h
4
6502.h
|
@ -16,8 +16,8 @@ uint8_t Y;
|
||||||
uint16_t PC;
|
uint16_t PC;
|
||||||
uint8_t SP; // points to first empty stack location
|
uint8_t SP; // points to first empty stack location
|
||||||
|
|
||||||
void * readAddr;
|
void * read_addr;
|
||||||
void * writeAddr;
|
void * write_addr;
|
||||||
|
|
||||||
struct StatusBits{
|
struct StatusBits{
|
||||||
int carry:1; // bit 0
|
int carry:1; // bit 0
|
||||||
|
|
16
6850.c
16
6850.c
|
@ -15,7 +15,7 @@ void init_uart() {
|
||||||
uart_SR.bits.TDRE = 1; // we are always ready to output data
|
uart_SR.bits.TDRE = 1; // we are always ready to output data
|
||||||
|
|
||||||
uart_SR.bits.RDRF = 0;
|
uart_SR.bits.RDRF = 0;
|
||||||
incomingChar = 0;
|
incoming_char = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,22 +27,22 @@ int stdin_ready() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void step_uart() {
|
void step_uart() {
|
||||||
if (writeAddr == &memory[DATA_ADDR]) {
|
if (write_addr == &memory[DATA_ADDR]) {
|
||||||
putchar(memory[DATA_ADDR]);
|
putchar(memory[DATA_ADDR]);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
writeAddr = NULL;
|
write_addr = NULL;
|
||||||
} else if (readAddr == &memory[DATA_ADDR]) {
|
} else if (read_addr == &memory[DATA_ADDR]) {
|
||||||
uart_SR.bits.RDRF = 0;
|
uart_SR.bits.RDRF = 0;
|
||||||
readAddr = NULL;
|
read_addr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update input register if empty */
|
/* update input register if empty */
|
||||||
if ((n++ % 10000) == 0) { // polling stdin every cycle is performance intensive. This is a bit of a dirty hack.
|
if ((n++ % 10000) == 0) { // polling stdin every cycle is performance intensive. This is a bit of a dirty hack.
|
||||||
if (!uart_SR.bits.RDRF && stdin_ready()) { // the real hardware has no buffer. Remote the RDRF check for more accurate emulation.
|
if (!uart_SR.bits.RDRF && stdin_ready()) { // the real hardware has no buffer. Remote the RDRF check for more accurate emulation.
|
||||||
if (read(0, &incomingChar, 1) != 1) {
|
if (read(0, &incoming_char, 1) != 1) {
|
||||||
printf("Warning: read() returned 0\n");
|
printf("Warning: read() returned 0\n");
|
||||||
}
|
}
|
||||||
if (incomingChar == 0x18) { // CTRL+X
|
if (incoming_char == 0x18) { // CTRL+X
|
||||||
printf("\r\n");
|
printf("\r\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,6 @@ void step_uart() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memory[DATA_ADDR] = incomingChar;
|
memory[DATA_ADDR] = incoming_char;
|
||||||
memory[CTRL_ADDR] = uart_SR.byte;
|
memory[CTRL_ADDR] = uart_SR.byte;
|
||||||
}
|
}
|
||||||
|
|
2
6850.h
2
6850.h
|
@ -19,7 +19,7 @@ union UartStatusReg {
|
||||||
|
|
||||||
union UartStatusReg uart_SR;
|
union UartStatusReg uart_SR;
|
||||||
|
|
||||||
uint8_t incomingChar;
|
uint8_t incoming_char;
|
||||||
|
|
||||||
void init_uart();
|
void init_uart();
|
||||||
|
|
||||||
|
|
71
main.c
71
main.c
|
@ -1,71 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "6502.h"
|
|
||||||
#include "6850.h"
|
|
||||||
|
|
||||||
struct termios oldTermios;
|
|
||||||
|
|
||||||
void step_delay()
|
|
||||||
{
|
|
||||||
struct timespec req, rem;
|
|
||||||
|
|
||||||
req.tv_sec = 0;
|
|
||||||
req.tv_nsec = STEP_DURATION;
|
|
||||||
|
|
||||||
nanosleep(&req, &rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
void run_cpu()
|
|
||||||
{
|
|
||||||
for (;;) {
|
|
||||||
// CPU timing is currently very far from being cycle-accurate
|
|
||||||
for (int i = 0; i < (CPU_FREQ / (ONE_SECOND / STEP_DURATION)); i++) {
|
|
||||||
step_cpu();
|
|
||||||
step_uart();
|
|
||||||
}
|
|
||||||
step_delay(); // remove this for more speed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void restore_stdin()
|
|
||||||
{
|
|
||||||
tcsetattr(0, TCSANOW, &oldTermios);
|
|
||||||
}
|
|
||||||
|
|
||||||
void raw_stdin()
|
|
||||||
{
|
|
||||||
struct termios newTermios;
|
|
||||||
|
|
||||||
tcgetattr(0, &oldTermios);
|
|
||||||
newTermios = oldTermios;
|
|
||||||
cfmakeraw(&newTermios);
|
|
||||||
tcsetattr(0, TCSANOW, &newTermios);
|
|
||||||
atexit(restore_stdin);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
if (argc != 2) {
|
|
||||||
printf("Usage: %s file.rom\n", argv[0]);
|
|
||||||
printf("The first 16k of \"file.rom\" is loaded into the last 16k of memory.\n");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (load_rom(argv[1]) != 0) {
|
|
||||||
printf("Error loading \"%s\".\n", argv[1]);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
raw_stdin(); // allow individual keystrokes to be detected
|
|
||||||
|
|
||||||
init_tables();
|
|
||||||
init_uart();
|
|
||||||
|
|
||||||
reset_cpu();
|
|
||||||
run_cpu();
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user