From b66ddfb4a8692757f7887788d3a41a413b9567d8 Mon Sep 17 00:00:00 2001 From: Ruthenic Date: Tue, 24 May 2022 16:54:33 -0400 Subject: [PATCH] initial commit --- .gitignore | 1 + LICENSE | 3 + Makefile | 28 +++++++ compile_flags.txt | 2 + examples/as65 | Bin 0 -> 60268 bytes examples/bubble.asm | 42 ++++++++++ examples/hi.asm | 4 + examples/make.sh | 8 ++ lib/constants.h | 27 +++++++ lib/file.h | 11 +++ src/emu.c | 183 ++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 85 ++++++++++++++++++++ 12 files changed, 394 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 compile_flags.txt create mode 100755 examples/as65 create mode 100644 examples/bubble.asm create mode 100644 examples/hi.asm create mode 100755 examples/make.sh create mode 100644 lib/constants.h create mode 100644 lib/file.h create mode 100644 src/emu.c create mode 100644 src/main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e660fd9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..14fb13d --- /dev/null +++ b/LICENSE @@ -0,0 +1,3 @@ +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9a99972 --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +CC ?= gcc +target ?= $(shell ${CC} -dumpmachine) +CC_FLAGS ?= +CC_FLAGS := ${CC_FLAGS} -Ilib +DESTDIR ?= / + +.PHONY: all debug clean build-release install +all: + @$(shell mkdir -p bin) +all: main + +main: + @${CC} -o bin/main src/main.c ${CC_FLAGS} + +debug: CC_FLAGS:=-g -O0 -v -fsanitize=undefined -fsanitize=address ${CC_FLAGS} +debug: all + +clean: + @rm -rf bin + +release: CC_FLAGS:=-O3 ${CC_FLAGS} +release: all +release: + @strip bin/* + tar -czf release.tar.gz bin/* + +install: + @install -m 777 bin/main ${DESTDIR}/usr/local/bin diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 0000000..7784424 --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1,2 @@ +-Ilib +-DDRAKECU_VERSION="placeholder" diff --git a/examples/as65 b/examples/as65 new file mode 100755 index 0000000000000000000000000000000000000000..67af97b7aac81886a5f65bd2ecdbc6120d8bb1c2 GIT binary patch literal 60268 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

f%B+`dH{J<)BLcy=F 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 RX +#include + +uint8_t memory[0xFFFF + 1]; //16kib memory (probably) + //0x0000 - 0x00FF is Zero Paged + //0x0100 - 0x01FF is system stack + +uint16_t prc = 0; //16bit program counter + +uint8_t spt = 0; //8bit stack pointer + +uint8_t acc = 0; //8bit accumulator +uint8_t irx,iry = 0; //2 8bit index registers + +struct status { + bool carry; //carry flag + bool zero; //zero flag + bool ird; //interrupt disable flag + bool dec; //decimal mode flag for arithmetic + bool brk; //break bit + bool overflow; //overflow flag + bool neg; //negative flag +}; + + +struct status cpuStatus; diff --git a/lib/file.h b/lib/file.h new file mode 100644 index 0000000..5b2037d --- /dev/null +++ b/lib/file.h @@ -0,0 +1,11 @@ +#include + +int8_t bin[] = { + 0xa9, 0x05, 0x85, 0x30, 0x85, 0x33, 0xa9, 0xa4, 0x85, 0x34, 0xa9, 0x07, + 0x85, 0x35, 0xa9, 0xf6, 0x85, 0x36, 0xa9, 0x44, 0xa5, 0x37, 0xa0, 0x00, + 0x84, 0x32, 0xb1, 0x30, 0xaa, 0xc8, 0xca, 0xb1, 0x30, 0xc8, 0xd1, 0x30, + 0x90, 0x10, 0xf0, 0x0e, 0x48, 0xb1, 0x30, 0x88, 0x91, 0x30, 0x68, 0xc8, + 0x91, 0x30, 0xa9, 0xff, 0x85, 0x32, 0xca, 0xd0, 0xe6, 0x24, 0x32, 0x30, + 0xd9, 0x60 +}; +unsigned int __6502_functional_test_bin_len = 62; diff --git a/src/emu.c b/src/emu.c new file mode 100644 index 0000000..6f6ae41 --- /dev/null +++ b/src/emu.c @@ -0,0 +1,183 @@ +#include "constants.h" + +#include +#include +#include + +void memview() { + for (int i = 0x00; i <= 0xFFFF; i++) { + if (memory[i] != 0x00) { + //printf("Mem Address 0x%04X: 0x%04X\n", i, memory[i]); + } + } + printf("irx - %d\n", irx); + printf("iry - %d\n", iry); + printf("acc - %d\n", acc); +} + +int emulate(uint8_t exec[], int size, uint8_t addr) { + //uint8_t* program = (uint8_t*)exec; + for (int i = addr, i2=0; i < size+addr; i++) { + memory[i] = exec[i2]; + i2++; + } + + while (prc < size) { + uint8_t inst = memory[addr+prc]; + switch (inst) { + //BRK + case 0x00: + cpuStatus.brk = 0x01; + prc++; + prc++; + break; + //NOP + case 0xEA: + prc++; + break; + case 0x80: + prc++; + break; + + //variations on an INC + case 0xE6: + memory[memory[++prc+addr]]++; + prc++; + break; + case 0xE8: + irx++; + prc++; + break; + case 0xC8: + iry++; + prc++; + break; + + //LDA + case 0xA9: { + uint8_t mem = memory[memory[++prc+addr]]; + acc = mem; + prc++; + break; + } + case 0xA5: { + uint8_t mem = memory[memory[++prc+addr]]; + acc = mem; + prc++; + break; + } + case 0xB1: { + uint8_t mem = memory[(++prc)+addr]; + mem+=iry; + acc = memory[mem]; + prc++; + break; + } + + //STA + case 0x85: { + memory[memory[++prc+addr]] = acc; + prc++; + break; + } + + //STY + case 0x84: { + memory[memory[++prc+addr]] = iry; + prc++; + break; + } + + //variations on an LDY (it doesn't work as well the second time) + case 0xA0: { + uint8_t mem = memory[memory[++prc+addr]]; + iry = mem; + prc++; + break; + } + + //ORA + case 0x01: { + uint8_t mem = memory[(++prc)+addr]; + mem+=irx; + uint8_t val = memory[mem]; + acc = acc | val; + prc++; + break; + } + + //TAX + case 0xAA: { + irx = acc; + if (irx == 0) { + cpuStatus.zero = 1; + } else { + cpuStatus.zero = 0; + } + prc++; + break; + } + + //DEX + case 0xCA: { + irx--; + if (irx == 0) { + cpuStatus.zero = 1; + } else { + cpuStatus.zero = 0; + } + prc++; + break; + } + case 0xD1: { + uint8_t mem = memory[(++prc)+addr]; + mem+=iry; + mem = memory[mem]; + if (acc >= mem) { + cpuStatus.carry = 1; + } else { + cpuStatus.carry = 0; + } + + if (acc == mem) { + cpuStatus.zero = 1; + } else { + cpuStatus.zero = 0; + } + prc++; + break; + } + + + case 0x90: { + uint8_t mem = memory[memory[++prc+addr]]; + if (cpuStatus.carry == 0x00) { + prc += mem; + } + break; + } + case 0x10: { + uint8_t mem = memory[memory[++prc+addr]]; + if (cpuStatus.neg == 0x00) { + prc += mem; + } + break; + } + case 0xF0: { + uint8_t mem = memory[memory[++prc+addr]]; + if (cpuStatus.zero == 0x00) { + prc += mem; + } + break; + } + + default: + printf("Opcode 0x%02X\n not implemented!\n", inst); + _exit(0); + } + printf("Ran inst 0x%02X\n", inst); + memview(); + } + + return 0; +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..a4c0420 --- /dev/null +++ b/src/main.c @@ -0,0 +1,85 @@ +#include "constants.h" +#include "file.h" + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#include "emu.c" + +uint16_t* fileRead(char* name) { + FILE* fp = fopen(name, "rb"); + if (!(access(name, F_OK) == 0)) { + errno = -1; + printf("Hi?\n"); + return 0; + } + + struct stat st; + stat(name, &st); + int length = st.st_size; + + uint16_t rbuf[length+1]; + + for (int i = 0; i < length; i++) { + fread(&rbuf[i], 2, 1, fp); + } + fclose(fp); + + uint16_t* tmp = rbuf; + return tmp; +} + +//blanks out memory and initializes various things +int init() { + for (int i = 0; i <= 0xFFFF; i++) { //blank memory + memory[i] = 0x00; + } + + cpuStatus.brk = 0; + cpuStatus.carry = 0; + cpuStatus.dec = 0; + cpuStatus.ird = 0; + cpuStatus.neg = 0; + cpuStatus.overflow = 0; + cpuStatus.zero = 0; + + return 0; +} + +void help(char* exe) { + printf("%s - a 6502 emulator.\n" + " Usage: %s [prg]", exe, exe); +} + +int main(int argc, char* argv[]) { + char* filename = *++argv; //TODO: jankiest thing ever + + /*uint16_t* binary = (uint16_t*)fileRead(filename); + + //uint16_t binary[] = {0xe7e6, 0xeaea, 0x01e6, 0xe8ea, 0xc8ea, 0x00ea}; + int size = sizeof(binary)/sizeof(binary[0])+1; + uint8_t exec[size*2]; + for (int i,i2 = 0; i < size-1; i++) { + printf("%04X\n", binary[i]); + uint8_t lsb = (binary[i] & 0xFF); + uint8_t hsb = (binary[i] & 0xFF00) >> 8; + exec[i2] = lsb; + exec[++i2] = hsb; + i2++; + }*/ + uint8_t* exec = (uint8_t*)bin; + int size = __6502_functional_test_bin_len; + printf("Program ROM:\n"); + for (int i = 0; i < size; i++) { + printf("0x%02X\n", exec[i]); + } + emulate(exec, size, 0x0400); //hacky lol + return 0; +}