mirror of
https://github.com/been-jamming/A1Emu.git
synced 2024-11-21 15:31:15 +00:00
First commit
This commit is contained in:
parent
6b2cc3b2da
commit
6b2d4c09a3
18
Makefile
Normal file
18
Makefile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
CC = gcc
|
||||||
|
|
||||||
|
CFLAGS = -O3
|
||||||
|
|
||||||
|
default: cpu.o cpu.h emulate.c
|
||||||
|
$(CC) $(CFLAGS) cpu.o emulate.c -o A1Emu
|
||||||
|
|
||||||
|
cpu.o: cpu.c cpu.h
|
||||||
|
$(CC) $(CFLAGS) -c cpu.c
|
||||||
|
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
clean:
|
||||||
|
del A1Emu.exe cpu.o
|
||||||
|
else
|
||||||
|
clean:
|
||||||
|
rm A1Emu cpu.o
|
||||||
|
endif
|
||||||
|
|
40
cpu.h
Normal file
40
cpu.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* 6502 Emulator
|
||||||
|
*
|
||||||
|
* Spring Break programming project
|
||||||
|
*
|
||||||
|
* 3/5/2019
|
||||||
|
* by Ben Jones
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
//Bits of the status register and correseponding flags
|
||||||
|
#define CARRY 0
|
||||||
|
#define ZERO 1
|
||||||
|
#define INTERRUPT 2
|
||||||
|
#define DECIMAL 3
|
||||||
|
#define BREAK 4
|
||||||
|
#define OVERFLOW 6
|
||||||
|
#define NEGATIVE 7
|
||||||
|
|
||||||
|
typedef struct CPU_6502 CPU_6502;
|
||||||
|
|
||||||
|
//Store the state of cpu
|
||||||
|
struct CPU_6502{
|
||||||
|
//The ALU loads and stores to and from the accumulator
|
||||||
|
uint8_t A_reg;
|
||||||
|
//Index registers
|
||||||
|
uint8_t X_reg;
|
||||||
|
uint8_t Y_reg;
|
||||||
|
//The stack pointer is actually a 16 bit value but the first byte is hard-wired to 0x01, so you only need 8 bits to store it
|
||||||
|
uint8_t SP_reg;
|
||||||
|
uint16_t PC_reg;
|
||||||
|
//The bits status register are all of the processor flags, but it is its own register whose value can be pushed to the stack
|
||||||
|
uint8_t P_reg;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void execute_6502(CPU_6502 *cpu, uint8_t (*read)(uint16_t), void (*write)(uint16_t, uint8_t));
|
||||||
|
|
||||||
|
void reset_6502(CPU_6502 *cpu, uint8_t (*read)(uint16_t));
|
137
emulate.c
Normal file
137
emulate.c
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <conio.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
|
unsigned DEBUG_STEP = 0;
|
||||||
|
|
||||||
|
uint8_t memory[0x10000];
|
||||||
|
|
||||||
|
void print_state(CPU_6502 cpu){
|
||||||
|
printf("A: %02x X:%02x Y:%02x SP:%02x P:%02x PC:%02x\n", (int) cpu.A_reg, (int) cpu.X_reg, (int) cpu.Y_reg, (int) cpu.SP_reg, (int) cpu.P_reg, (int) cpu.PC_reg);
|
||||||
|
printf("\nNext: %02x %02x %02x\n", (int) memory[cpu.PC_reg], (int) memory[cpu.PC_reg + 1], (int) memory[cpu.PC_reg + 2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Special read memory routine for memory-mapped I/O
|
||||||
|
uint8_t read_mem(uint16_t index){
|
||||||
|
uint8_t output;
|
||||||
|
|
||||||
|
if(DEBUG_STEP){
|
||||||
|
printf("READ: %04x ", index);
|
||||||
|
}
|
||||||
|
output = memory[index];
|
||||||
|
if(index == 0xD010){
|
||||||
|
memory[0xD011] &= 0x7F;
|
||||||
|
} else if((index&0xFF0F) == 0xD002){
|
||||||
|
output = 0;
|
||||||
|
}
|
||||||
|
if(DEBUG_STEP){
|
||||||
|
printf("%02x\n", memory[index]);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Special write memory routine for memory mapped I/O
|
||||||
|
void write_mem(uint16_t index, uint8_t value){
|
||||||
|
uint8_t x;
|
||||||
|
uint8_t y;
|
||||||
|
|
||||||
|
if(DEBUG_STEP){
|
||||||
|
printf("WRITE: %02x --> %04x\n", value, index);
|
||||||
|
}
|
||||||
|
if((index&0xFF0F) == 0xD002){
|
||||||
|
if((value&0x7F) == '\n' || (value&0x7F) == '\r'){
|
||||||
|
printf("\n");
|
||||||
|
} else if((value&0x7F) >= 0x20 && (value&0x7F) != 127){
|
||||||
|
//Output a character
|
||||||
|
printf("%c", value&0x7F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memory[index] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
CPU_6502 cpu;
|
||||||
|
FILE *fp;
|
||||||
|
unsigned char key_hit;
|
||||||
|
unsigned int count = 0;
|
||||||
|
unsigned long int last_time;
|
||||||
|
unsigned long int next_time;
|
||||||
|
struct timeval current_time;
|
||||||
|
|
||||||
|
cpu.A_reg = 0;
|
||||||
|
cpu.X_reg = 0;
|
||||||
|
cpu.Y_reg = 0;
|
||||||
|
cpu.SP_reg = 0;
|
||||||
|
cpu.P_reg = 0;
|
||||||
|
cpu.PC_reg = 0xE000;
|
||||||
|
|
||||||
|
//Load Integer Basic
|
||||||
|
fp = fopen("BASIC", "rb");
|
||||||
|
if(fp){
|
||||||
|
fread(memory + 0xE000, 1, 0x2000, fp);
|
||||||
|
} else {
|
||||||
|
printf("file error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
//The emulator does not support ACI at the moment
|
||||||
|
|
||||||
|
//Load Woz's monitor
|
||||||
|
fp = fopen("WOZMON", "rb");
|
||||||
|
if(fp){
|
||||||
|
fread(memory + 0xFF00, 1, 0x100, fp);
|
||||||
|
} else {
|
||||||
|
printf("file error 3\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
reset_6502(&cpu, read_mem);//Reset the cpu
|
||||||
|
|
||||||
|
//Initialize the timing
|
||||||
|
gettimeofday(¤t_time, NULL);
|
||||||
|
last_time = current_time.tv_usec + current_time.tv_sec*1000000;
|
||||||
|
while(1){
|
||||||
|
/*Limit the speed of the processor to
|
||||||
|
* a realistic 4usec per instruction
|
||||||
|
*
|
||||||
|
* Will count cpu cycles soon to make
|
||||||
|
* better timing.
|
||||||
|
*/
|
||||||
|
do{
|
||||||
|
gettimeofday(¤t_time, NULL);
|
||||||
|
next_time = current_time.tv_usec + current_time.tv_sec*1000000;
|
||||||
|
} while(next_time - last_time < 4);
|
||||||
|
last_time = last_time + 4;
|
||||||
|
|
||||||
|
//Execute the instruction
|
||||||
|
execute_6502(&cpu, read_mem, write_mem);
|
||||||
|
count = count + 1;
|
||||||
|
|
||||||
|
//Debugging I/O
|
||||||
|
if(DEBUG_STEP){
|
||||||
|
print_state(cpu);
|
||||||
|
key_hit = getchar();
|
||||||
|
if(key_hit == '|'){
|
||||||
|
DEBUG_STEP = 0;
|
||||||
|
} else if(key_hit != ' '){
|
||||||
|
memory[0xD010] = key_hit|0x80;
|
||||||
|
memory[0xD011] = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Handle keyboard I/O
|
||||||
|
if(!(count%200) && kbhit()){
|
||||||
|
key_hit = getch();
|
||||||
|
|
||||||
|
if(key_hit == '|'){
|
||||||
|
DEBUG_STEP = 1;
|
||||||
|
} else {
|
||||||
|
memory[0xD010] = key_hit|0x80;
|
||||||
|
memory[0xD011] |= 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user