Skip to content

Commit 58f03ba

Browse files
committed
initial commit
0 parents  commit 58f03ba

20 files changed

+17607
-0
lines changed

.devcontainer/Dockerfile

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
FROM debian:11
2+
3+
ARG PACKAGES="\
4+
ca-certificates \
5+
curl \
6+
dasm \
7+
file \
8+
gcc \
9+
gdb \
10+
git \
11+
lbzip2 \
12+
less \
13+
libc6-dev \
14+
locales \
15+
lsb-release \
16+
make \
17+
man \
18+
manpages \
19+
manpages-dev \
20+
procps \
21+
ssh \
22+
sudo \
23+
vim \
24+
xz-utils"
25+
26+
# Install system packages
27+
RUN apt-get update \
28+
&& export DEBIAN_FRONTEND=noninteractive \
29+
&& apt-get -y upgrade --no-install-recommends \
30+
&& apt-get -y install --no-install-recommends ${PACKAGES}
31+
32+
# Update locales for en_US.UTF-8
33+
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
34+
dpkg-reconfigure --frontend=noninteractive locales && \
35+
update-locale LANG=en_US.UTF-8
36+
37+
# Create user
38+
ARG USERNAME=coder
39+
ARG USER_UID=1000
40+
ARG USER_GID=$USER_UID
41+
RUN groupadd --gid ${USER_GID} ${USERNAME} \
42+
&& useradd -s /bin/bash --uid ${USER_UID} --gid ${USER_GID} -m ${USERNAME}
43+
44+
# Give user sudo permissions
45+
RUN echo ${USERNAME} ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/${USERNAME} \
46+
&& chmod 0440 /etc/sudoers.d/${USERNAME}
47+
48+
# Switch to user and configure terminal
49+
USER $USERNAME
50+
ARG TERM=xterm-256color
51+
ENV TERM=${TERM}

.devcontainer/devcontainer.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// https://aka.ms/devcontainer.json
2+
{
3+
"name": "nes",
4+
"build": {
5+
"dockerfile": "Dockerfile"
6+
},
7+
"extensions": [
8+
"ms-vscode.cpptools"
9+
],
10+
"settings": {
11+
"[c]": {
12+
"editor.tabSize": 4,
13+
"editor.insertSpaces": true
14+
}
15+
},
16+
17+
// support ptrace-based debuggers
18+
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
19+
20+
"mounts": [
21+
"source=${localEnv:HOME}${localEnv:USERPROFILE}/.ssh,target=/home/coder/.ssh,type=bind,consistency=cached"
22+
],
23+
24+
"remoteUser": "coder"
25+
}

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
bin/
2+
obj/
3+
*.swp
4+
*.swo

.vscode/c_cpp_properties.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"configurations": [
3+
{
4+
"name": "default",
5+
"intelliSenseMode": "linux-gcc-x64",
6+
"compilerPath": "/usr/bin/gcc",
7+
"cStandard": "gnu17",
8+
"cppStandard": "c++17",
9+
"includePath": [
10+
"src"
11+
]
12+
}
13+
],
14+
"version": 4
15+
}

Makefile

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
.PHONY: example clean test
2+
3+
CC := gcc
4+
CFLAGS := -Wall -Wextra -g
5+
6+
example: bin/compy bin/program.bin
7+
@./bin/compy ./bin/program.bin
8+
9+
clean:
10+
rm -rf obj/
11+
rm -rf bin/
12+
13+
obj/bus.o: src/bus.c src/bus.h
14+
@mkdir -p obj
15+
$(CC) $(CFLAGS) -c -o obj/bus.o $<
16+
17+
obj/cpu.o: src/cpu.c src/cpu.h src/bus.h
18+
@mkdir -p obj
19+
$(CC) $(CFLAGS) -c -o obj/cpu.o $<
20+
21+
obj/main.o: example/main.c src/bus.h src/cpu.h
22+
@mkdir -p obj
23+
$(CC) $(CFLAGS) -Isrc -c -o obj/main.o $<
24+
25+
bin/compy: obj/bus.o obj/cpu.o obj/main.o
26+
@mkdir -p bin
27+
$(CC) $(CFLAGS) $^ -o bin/compy
28+
29+
bin/program.bin: example/program.asm
30+
@mkdir -p bin
31+
dasm $< -f3 -obin/program.bin
32+
33+
test: bin/bus_test bin/cpu_test bin/6502_functional_test
34+
@./bin/bus_test
35+
@./bin/cpu_test
36+
@./bin/6502_functional_test
37+
38+
bin/bus_test: test/test.c test/test.h test/bus_test.c obj/bus.o
39+
@mkdir -p bin
40+
$(CC) -o bin/bus_test $(CFLAGS) -Isrc $^
41+
42+
bin/cpu_test: test/test.c test/test.h test/cpu_test.c obj/bus.o obj/cpu.o
43+
@mkdir -p bin
44+
$(CC) -o bin/cpu_test $(CLFAGS) -Isrc $^
45+
46+
bin/6502_functional_test: test/test.c test/test.h test/6502_functional_test.c obj/bus.o obj/cpu.o
47+
@mkdir -p bin
48+
$(CC) -o bin/6502_functional_test $(CLFAGS) -Isrc $^

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# 6502

example/main.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
5+
#include "bus.h"
6+
#include "cpu.h"
7+
8+
const char * banner =
9+
"#################\n"
10+
"# COMPY #\n"
11+
"#################\n\n";
12+
13+
static struct memory {
14+
uint8_t ram[0x8000];
15+
uint8_t rom[0x8000];
16+
} memory;
17+
18+
static uint8_t peek(void *inst, uint16_t addr) {
19+
struct memory *mem = (struct memory *)inst;
20+
21+
if (addr < 0x8000) {
22+
return mem->ram[addr];
23+
} else {
24+
return mem->rom[addr - 0x8000];
25+
}
26+
}
27+
28+
static void poke(void *inst, uint16_t addr, uint8_t data) {
29+
struct memory *mem = (struct memory *)inst;
30+
31+
if (addr < 0x8000) {
32+
mem->ram[addr] = data;
33+
}
34+
}
35+
36+
static size_t load(FILE *bin) {
37+
uint8_t binbuf[0x10000];
38+
39+
size_t bytes_read = fread(binbuf, 1, 0x10000, bin);
40+
41+
if (bytes_read < 0x8000) {
42+
memcpy(memory.ram, binbuf, bytes_read);
43+
return bytes_read;
44+
}
45+
46+
memcpy(memory.ram, binbuf, 0x8000);
47+
memcpy(memory.rom, binbuf + 0x8000, bytes_read - 0x8000);
48+
return bytes_read;
49+
}
50+
51+
int main(int argc, char *argv[]) {
52+
struct bus bus = {
53+
.inst = &memory,
54+
.peek = peek,
55+
.poke = poke
56+
};
57+
58+
if (argc != 2) {
59+
printf("Usage: compy <program>\n");
60+
return 1;
61+
}
62+
63+
FILE *bin = fopen(argv[1], "r");
64+
if (bin == NULL) {
65+
printf("ERROR: unable to open %s\n", argv[1]);
66+
return 1;
67+
}
68+
69+
size_t bytes_read = load(bin);
70+
fclose(bin);
71+
72+
if (bytes_read != 0x10000) {
73+
printf("ERROR: program file is not 0x10000 bytes\n");
74+
return 1;
75+
}
76+
77+
uint16_t pc_start = bus_peek(&bus, 0xFFFD);
78+
pc_start = pc_start << 8 | bus_peek(&bus, 0xFFFC);
79+
80+
struct cpu cpu;
81+
cpu_init(&cpu, pc_start);
82+
83+
printf(banner);
84+
85+
uint16_t prev_pc;
86+
do {
87+
prev_pc = cpu.pc;
88+
cpu_step(&cpu, &bus);
89+
} while (prev_pc != cpu.pc);
90+
91+
printf("Result of computation is: %d\n", memory.ram[0]);
92+
93+
return 0;
94+
}

example/program.asm

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
processor 6502
2+
3+
org $0000,0
4+
ds $8000
5+
6+
org $8000
7+
start:
8+
lda #1
9+
adc #2
10+
sta 0
11+
trap:
12+
jmp trap
13+
14+
org $FFFA
15+
dc.w start
16+
dc.w start
17+
dc.w start

src/bus.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <stdlib.h>
2+
3+
#include "bus.h"
4+
5+
uint8_t bus_peek(const struct bus *bus, uint16_t addr) {
6+
return bus->peek(bus->inst, addr);
7+
}
8+
9+
void bus_poke(const struct bus *bus, uint16_t addr, uint8_t data) {
10+
bus->poke(bus->inst, addr, data);
11+
}

src/bus.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef __BUS_H__
2+
#define __BUS_H__
3+
4+
#include <stdint.h>
5+
6+
struct bus {
7+
void *inst;
8+
uint8_t (*peek)(void *inst, uint16_t addr);
9+
void (*poke)(void *inst, uint16_t addr, uint8_t data);
10+
};
11+
12+
13+
uint8_t bus_peek(const struct bus *bus, uint16_t addr);
14+
void bus_poke(const struct bus *bus, uint16_t addr, uint8_t data);
15+
16+
#endif

0 commit comments

Comments
 (0)